Redis 生产可靠性、数据安全与故障排查完整指南
Redis 的性能问题通常不是“命令执行慢”这么简单。生产事故往往由容量失控、热 Key、大 Key、持久化抖动、复制积压、故障切换、客户端重试风暴和错误的淘汰策略共同引起。本文以“数据是否安全、服务是否可用、延迟是否稳定”为主线,给出从架构设计到故障处置的完整路线。
本文命令用于诊断思路示例。生产执行
FLUSHALL、KEYS *、大范围删除、主从切换、集群重分片等操作前,必须完成备份、评审并准备回滚方案。
一、先明确 Redis 承担什么角色
Redis 可以是缓存、会话存储、计数器、排行榜、分布式锁、消息缓冲,也可能被错误地当作唯一数据库。不同角色决定不同的可靠性目标。
| 使用方式 | 数据丢失容忍度 | 重点 |
|---|---|---|
| 可重建缓存 | 较高 | 命中率、穿透保护、淘汰策略 |
| 会话与验证码 | 中等 | 过期、跨节点一致性、切换时间 |
| 计数和状态 | 较低 | 持久化、复制、幂等补偿 |
| 队列或流 | 较低 | 消费确认、积压、死信与恢复 |
| 唯一数据源 | 极低 | 通常不建议,必须有额外持久化与恢复设计 |
上线前至少定义:RPO、RTO、峰值 QPS、P99 延迟、最大内存、单 Key 最大尺寸、连接数、增长速度和降级方式。
二、生产架构选择
1. 主从复制
适合读扩展和备份副本,但复制是异步的。主节点确认写入后宕机,尚未复制的数据可能丢失。只增加副本并不等于自动高可用。
2. Sentinel
Sentinel 负责监控、选主和通知,适合数据量能够放入单个主节点、无需水平分片的场景。生产至少部署三个独立 Sentinel,并避免全部落在同一宿主机、机架或故障域。
3. Redis Cluster
Cluster 将 16384 个槽分布到多个主节点,可扩展容量和吞吐。每个主节点应有副本,客户端必须支持重定向、拓扑刷新和连接恢复。多 Key 命令需要使用 Hash Tag 保证 Key 落在同一槽。
4. 代理方案
代理能简化客户端,但引入新的性能和可用性边界。必须监控代理连接池、排队、后端错误、拓扑刷新和代理自身高可用。
三、内存容量与淘汰策略
redis-cli INFO memory
redis-cli INFO stats
redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli MEMORY STATS
重点指标:
used_memory:Redis 分配器统计的内存;used_memory_rss:操作系统观察到的常驻内存;mem_fragmentation_ratio:只能作为线索,不能单独判断故障;evicted_keys:发生淘汰的累计数量;expired_keys:过期删除量;keyspace_hits/misses:缓存命中情况;- 容器限制、宿主机可用内存和 fork 峰值。
不要把 maxmemory 设置为宿主机或容器的全部内存。还要为复制缓冲区、客户端缓冲区、AOF、RDB fork、内存碎片和内核预留空间。常见做法是根据工作负载保留 20%~40% 余量,再用压测确认。
淘汰策略必须与数据语义一致:
noeviction:达到上限后拒绝写入,适合不能静默淘汰的数据;allkeys-lru/lfu:所有 Key 都可参与淘汰,常用于纯缓存;volatile-lru/lfu/ttl:只淘汰设置过期时间的 Key;allkeys-random/volatile-random:行为简单,但命中率通常不如 LRU/LFU。
四、RDB、AOF与数据恢复
RDB 生成时间点快照,文件紧凑、恢复快,但两次快照之间的数据可能丢失。AOF 记录写命令,通常可将 RPO 缩短到秒级,但文件更大,重写期间会产生额外 I/O 和内存压力。
常见组合是开启 RDB 和 AOF:RDB 用于周期备份与快速恢复,AOF 用于降低近期数据丢失。需要注意:开启持久化不等于完成备份,误删除、逻辑错误和勒索加密会同步到在线文件。
redis-cli INFO persistence
redis-cli LASTSAVE
redis-cli BGSAVE
redis-cli BGREWRITEAOF
监控项包括:
- 最近一次 RDB/AOF 是否成功;
- fork 耗时和写时复制额外内存;
- AOF 重写时长、增量缓冲和文件大小;
- 数据盘延迟、剩余空间和 inode;
- 备份文件能否在隔离环境恢复。
备份应复制到独立存储,保留多代并定期演练。恢复演练要验证 Key 数量、业务抽样、过期时间、应用连接和回放后的数据一致性。
五、复制链路与故障切换
redis-cli INFO replication
redis-cli ROLE
redis-cli INFO server
重点检查:
- 主从偏移量差距;
master_link_status;- 最后一次 I/O 时间;
- 复制积压缓冲区是否足够;
- 是否频繁发生全量同步;
- 副本只读状态;
- 主从时钟和网络质量。
短暂断网后能否部分重同步取决于复制积压缓冲区是否覆盖断线期间的写入量。可按“峰值写入字节/秒 × 允许断线秒数 × 安全系数”估算,再结合内存余量调整。
切换前后应验证:
- 新主节点的复制偏移量和数据新鲜度;
- 客户端是否发现新主;
- 旧主恢复后是否正确降级为副本;
- 是否出现双主写入或 DNS/连接池缓存;
- 写入幂等与补偿任务是否生效。
六、大 Key、热 Key与倾斜
大 Key 会造成网络突发、主线程阻塞、删除抖动、复制延迟和迁移困难。热 Key 会把流量集中到单节点或单 CPU 主线程。
redis-cli --bigkeys
redis-cli --memkeys
redis-cli MEMORY USAGE '<key>' SAMPLES 5
redis-cli OBJECT ENCODING '<key>'
redis-cli SLOWLOG GET 20
redis-cli LATENCY DOCTOR
不要在高峰直接执行 KEYS *。应使用 SCAN 分批遍历,并控制 COUNT 和客户端速率。
治理方法:
- 拆分超大 Hash、List、Set 和 ZSet;
- 对可重建热点做本地缓存和请求合并;
- 让热点 Key 增加分片后缀并在应用聚合;
- 删除大 Key 使用
UNLINK,并观察 lazyfree 队列; - 业务写入设置合理 TTL,避免永久 Key 无边界增长;
- Cluster 环境监控槽位、Key 数和内存分布,而不只看总量。
七、延迟诊断
Redis 命令执行在主线程上串行推进,慢命令、fork、磁盘写入、内存回收、网络队列和虚拟化抖动都可能放大尾延迟。
redis-cli --latency
redis-cli --latency-history
redis-cli SLOWLOG LEN
redis-cli SLOWLOG GET 50
redis-cli LATENCY LATEST
redis-cli INFO commandstats
分层判断:
- 同机
redis-cli --latency是否异常; - 应用到 Redis 的网络 RTT 是否异常;
- Slow Log 是否出现耗时命令;
- 是否正在 RDB、AOF 重写或全量同步;
- CPU 是否被单核打满,是否存在 steal;
- 磁盘延迟和 fsync 是否升高;
- 客户端连接池是否排队或重建连接。
Slow Log 只记录命令执行时间,不包含排队和网络耗时。应用端必须同时记录连接等待、请求耗时、超时类型和重试次数。
八、连接与客户端缓冲区
redis-cli INFO clients
redis-cli CLIENT LIST
redis-cli CLIENT INFO
关注连接数、阻塞客户端、输出缓冲区、订阅客户端和长时间空闲连接。客户端应设置连接超时、命令超时、有限重试和指数退避,避免故障时所有实例同步重连。
高风险模式包括:
- 无限连接池;
- 超时后立即无上限重试;
- 发布订阅消费者处理过慢;
- 大结果集一次返回;
- 阻塞命令长期占用连接;
- 应用启动时批量加载全部缓存。
九、缓存穿透、击穿与雪崩
- 穿透:查询不存在的数据。可使用参数校验、空值短缓存或布隆过滤器;
- 击穿:热点 Key 过期瞬间大量回源。可使用单飞、互斥重建或逻辑过期;
- 雪崩:大量 Key 同时失效或 Redis 故障。应给 TTL 加抖动、分批预热、限制回源并准备降级数据。
缓存治理必须与数据库容量联动。Redis 发生故障时,最危险的不是缓存不可用,而是回源流量把数据库一起压垮。
十、常见故障处置
1. 内存接近上限
先确认增长来自 Key 数据、客户端缓冲、复制缓冲还是碎片;暂停非必要写入;识别异常业务和大 Key;评估扩容或迁移。不要在未知原因时直接重启,重启可能触发更大的缓存回源和恢复压力。
2. 延迟突然升高
冻结变更,保存 INFO all、Slow Log、Latency、系统 CPU/内存/磁盘和网络证据;检查持久化、同步和批量命令;从单节点、单命令、单客户端三个维度缩小范围。
3. 副本频繁全量同步
检查复制积压缓冲区、网络中断、超时、磁盘速度、主从版本和容器重启;全量同步本身会进一步消耗 CPU、内存和网络,需要先阻断循环触发原因。
4. Cluster 槽位异常
redis-cli --cluster check <host>:<port>
redis-cli CLUSTER INFO
redis-cli CLUSTER NODES
确认是槽未覆盖、节点失联、迁移中还是客户端拓扑未更新。修复前先备份并核对节点 ID,避免把旧节点或错误数据重新加入集群。
十一、监控与告警建议
至少覆盖:
- 可用性、角色和集群状态;
- 内存使用率、RSS、碎片和淘汰;
- QPS、命中率、错误、拒绝连接;
- P50/P95/P99 延迟;
- 连接数、阻塞客户端和输出缓冲;
- 主从延迟、链路状态、全量同步次数;
- RDB/AOF 成功状态和耗时;
- Key 总量、过期、增长率和槽位倾斜;
- CPU 单核、磁盘延迟、网络重传和容器 OOM。
告警需要区分症状和原因。例如“内存 80%”只是容量信号,“持续淘汰且命中率下降”才更接近业务风险。
十二、上线与巡检清单
- [ ] 明确缓存还是持久数据,定义 RPO/RTO;
- [ ] 高可用节点跨宿主机和故障域;
- [ ] 设置 maxmemory、淘汰策略和系统内存余量;
- [ ] 验证 RDB/AOF 与离线备份恢复;
- [ ] 客户端支持拓扑刷新、超时、退避和幂等;
- [ ] 有大 Key、热 Key、慢命令和槽位倾斜检查;
- [ ] TTL 有随机抖动,数据库有回源保护;
- [ ] 完成主故障、网络分区、磁盘满和副本落后演练;
- [ ] 变更有基线、灰度、观察窗口和回滚方案;
- [ ] 任何危险命令都经过权限控制和审计。
十三、结语
Redis 的可靠性不是靠某个配置参数获得的,而是数据分级、容量余量、复制拓扑、持久化、客户端行为和故障演练共同形成的。真正成熟的运行方式,是在故障前知道容量边界,在故障中限制连锁影响,在故障后能够用备份和证据恢复,而不是把“重启后暂时正常”当作闭环。
参考资料
- Redis Documentation:https://redis.io/docs/latest/
- Redis Administration:https://redis.io/docs/latest/operate/