Redis缓存优化与集群部署实战指南
前言
Redis凭借其极致的性能和丰富的数据结构,已成为现代互联网架构中不可或缺的组件。然而,"Redis很快"不等于"用Redis就一定快"。不当的使用方式、不合理的配置、缺失的监控,都可能让Redis成为系统的瓶颈。本文将从实战出发,全面介绍Redis的优化与集群部署。
一、内存优化策略
1.1 内存使用分析
# 连接Redis
redis-cli
# 内存概况
INFO memory
# 查看大Key
redis-cli --bigkeys
# 内存分析(Redis 4.0+)
MEMORY USAGE key_name
MEMORY DOCTOR
1.2 数据结构优化
# ❌ 散乱的String存储用户信息
SET user:1001:name "张三"
SET user:1001:email "zhangsan@example.com"
SET user:1001:age "25"
# 内存占用约 300 bytes/user
# ✅ 使用Hash存储(ziplist编码)
HSET user:1001 name "张三" email "zhangsan@example.com" age 25
# 内存占用约 120 bytes/user,节省60%
内存优化配置:
# redis.conf
# 小hash使用ziplist编码
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# 小list使用ziplist
list-max-ziplist-size -2
list-compress-depth 0
# 小set使用intset
set-max-intset-entries 512
# 小zset使用ziplist
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
1.3 缓存淘汰策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| noeviction | 不淘汰,写满报错 | 不推荐 |
| allkeys-lru | 所有key LRU淘汰 | 通用推荐 |
| volatile-lru | 过期key LRU淘汰 | 混合使用场景 |
| allkeys-lfu | 所有key LFU淘汰 | 热点数据明显 |
| volatile-ttl | 过期时间最近的淘汰 | 定时过期场景 |
# redis.conf
maxmemory 8gb
maxmemory-policy allkeys-lru
1.4 过期键清理
# 查看带过期时间的key数量
INFO keyspace
# 扫描即将过期的key
redis-cli --scan --pattern '*' | while read key; do
ttl=$(redis-cli TTL "$key")
if [ "$ttl" -gt 0 ] && [ "$ttl" -lt 300 ]; then
echo "Key: $key, TTL: $ttl"
fi
done
过期删除策略:
- 惰性删除:访问时检查是否过期
- 定期删除:每秒10次随机抽查
二、持久化方案
2.1 RDB vs AOF
RDB (快照)
优点: 恢复快、文件小、对性能影响小
缺点: 可能丢失最后一次快照后的数据
适用: 缓存场景、可容忍少量数据丢失
AOF (追加日志)
优点: 数据安全性高、可逐条恢复
缺点: 文件大、恢复慢、性能影响大
适用: 金融、订单等关键数据
混合模式 (Redis 4.0+)
aof-use-rdb-preamble yes
RDB快照 + AOF增量 = 兼顾性能和安全
2.2 推荐配置
# redis.conf
# RDB配置
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
# AOF配置
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec # 每秒同步,性能与安全的平衡
no-appendfsync-on-rewrite yes # 重写时不fsync
# 自动重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
2.3 备份脚本
#!/bin/bash
BACKUP_DIR="/data/backup/redis"
REDIS_DIR="/var/lib/redis"
# 触发BGSAVE
redis-cli BGSAVE
# 等待完成
while [ $(redis-cli INFO persistence | grep rdb_bgsave_in_progress | cut -d: -f2) -eq 1 ]; do
sleep 1
done
# 备份
cp ${REDIS_DIR}/dump.rdb ${BACKUP_DIR}/dump_$(date +%Y%m%d_%H%M).rdb
# 清理旧备份
find ${BACKUP_DIR} -name "dump_*.rdb" -mtime +7 -delete
三、哨兵模式(Sentinel)
3.1 架构
Clients
│
┌───────┼───────┐
▼ ▼ ▼
┌────────┐┌────────┐┌────────┐
│Sentinel││Sentinel││Sentinel│
│ 1 ││ 2 ││ 3 │
└───┬────┘└───┬────┘└───┬────┘
│ │ │
└────┬────┴────┬────┘
▼ ▼
┌────────┐┌────────┐┌────────┐
│ Master ││ Slave ││ Slave │
└────────┘└────────┘└────────┘
3.2 Sentinel配置
# sentinel.conf (每个Sentinel相同)
port 26379
# 监控master (至少2个sentinel同意才故障切换)
sentinel monitor mymaster 192.168.1.10 6379 2
# 主观下线判定时间
sentinel down-after-milliseconds mymaster 5000
# 故障切换超时
sentinel failover-timeout mymaster 30000
# 并行同步的slave数量
sentinel parallel-syncs mymaster 1
# 认证密码
sentinel auth-pass mymaster redis_password
3.3 Sentinel运维
# 查看集群状态
redis-cli -p 26379 SENTINEL masters
redis-cli -p 26379 SENTINEL slaves mymaster
# 手动故障切换
redis-cli -p 26379 SENTINEL failover mymaster
# 查看哨兵信息
redis-cli -p 26379 SENTINEL sentinels mymaster
四、Redis Cluster集群
4.1 架构特点
- 16384个哈希槽分布
- 无中心代理,客户端直连
- 自动故障检测和转移
- 支持在线扩容缩容
4.2 搭建集群
# 每个节点配置
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
# 创建集群(6个节点,3主3从)
redis-cli --cluster create \
192.168.1.11:6379 192.168.1.12:6379 192.168.1.13:6379 \
192.168.1.14:6379 192.168.1.15:6379 192.168.1.16:6379 \
--cluster-replicas 1
# 查看集群状态
redis-cli -c -h 192.168.1.11 -p 6379 CLUSTER NODES
redis-cli --cluster check 192.168.1.11:6379
# 添加新节点
redis-cli --cluster add-node 192.168.1.17:6379 192.168.1.11:6379
# 重新分片
redis-cli --cluster reshard 192.168.1.11:6379
4.3 集群运维注意事项
- 批量操作要求所有key在同一个slot → 用
{hashtag} - 事务只能在同一节点的key上执行
- 多key操作(如
MGET)只能在同slot执行 - 建议最少3主3从
五、性能问题排查
5.1 慢查询日志
# 配置
CONFIG SET slowlog-log-slower-than 10000 # 10ms
CONFIG SET slowlog-max-len 1000
# 查看
SLOWLOG GET 10
SLOWLOG LEN
SLOWLOG RESET
5.2 延迟排查
# 延迟基线测试
redis-cli --latency
redis-cli --latency-history
redis-cli --latency-dist
# 检查是否是持久化导致的
INFO persistence | grep rdb_bgsave_in_progress
INFO persistence | grep aof_rewrite_in_progress
# 命令延迟监控
redis-cli --intrinsic-latency 30
5.3 常见问题速查
| 问题 | 可能原因 | 解决 |
|---|---|---|
| 延迟突增 | fork子进程写RDB | 关闭THP, 减少fork频率 |
| OOM | maxmemory-policy=noeviction | 改为allkeys-lru |
| 连接数满 | 客户端没关连接 | 配置timeout, 加连接池 |
| 主从断连 | 复制缓冲区太小 | 增大repl-backlog-size |
| CPU飙高 | 大量key过期 | 分散过期时间, lazyfree |
总结
Redis运维的核心理念:
- 内存是命:合理设置maxmemory和淘汰策略
- 持久化要稳:RDB+AOF混合模式
- 高可用必备:至少Sentinel,量大上Cluster
- 监控不掉线:慢查询、内存、延迟持续监控
- 备份不偷懒:定期备份,异地存储