4. 主从复制故障与运维
主从复制是 Redis 高可用的基础,但它并不是“配置完就永远正常”的黑盒。生产环境里最常见的三类问题分别是:复制链路中断、复制延迟持续增大、主从数据不一致。三者往往互相牵连——链路中断会导致延迟指标失真,延迟过大又可能在切换时放大数据丢失。理解它们的成因与排查路径,比记住某条命令更重要。
一、复制中断:先分清“断开”还是“卡住”
复制中断的典型表现是 INFO replication 中从节点的 master_link_status 变为 down,或主节点上 slave0 的 state 不再是 online。常见成因可以归为四类:网络层(防火墙、安全组、端口不通、连接被重置)、认证与配置层(requirepass 与 masterauth 不匹配、ACL 用户权限不足)、资源层(主节点 client-output-buffer-limit slave 超限导致主节点主动断开从节点)、以及复制缓冲区层(repl-backlog-size 太小,从节点短暂断线后无法做部分重同步,只能触发全量同步)。
排查时建议按“先看状态、再看日志、最后看资源”的顺序。在主节点执行:
redis-cli -h 10.0.0.11 -p 6379 INFO replication
# 关注 role:master、connected_slaves、slaveN:ip=...,state=online,offset=...
redis-cli -h 10.0.0.11 -p 6379 CLIENT LIST TYPE slave
# 观察从节点连接是否频繁重建、omem 是否异常增长
在从节点执行:
redis-cli -h 10.0.0.12 -p 6379 INFO replication
# 关注 master_link_status、master_last_io_seconds_ago、master_sync_in_progress
redis-cli -h 10.0.0.12 -p 6379 INFO stats
# 关注 sync_full、sync_partial_ok、sync_partial_err
如果 sync_full 持续增长而 sync_partial_ok 不增长,说明每次重连都在做全量同步,通常指向 backlog 过小或从节点断线时间过长。修复方向是调大 repl-backlog-size(例如从默认 1MB 提升到 64MB,具体按写入量和断线容忍时间估算),并检查网络稳定性。若是缓冲区超限,需要评估从节点消费能力,适当调大 client-output-buffer-limit slave 的 hard/soft 阈值,但更根本的是解决从节点慢的问题。
二、复制延迟:offset 差值是核心指标
复制延迟的本质是主节点写入速度超过从节点应用速度。判断延迟不能只看 master_last_io_seconds_ago,更可靠的是比较主从的复制偏移量。主节点 INFO replication 中每个从节点都有 offset,从节点自身也有 slave_repl_offset,两者差值就是尚未同步的字节量。差值持续增大,说明从节点跟不上。
常见原因包括:从节点执行了 DEBUG SLEEP 或 KEYS 等阻塞命令;存在大 key(如百万元素的 Hash、List),单条命令传播耗时高;主节点写入 QPS 过高,网络带宽成为瓶颈;从节点开启了 AOF appendfsync always,磁盘 IO 拖慢应用速度。排查时可在从节点执行 redis-cli --latency 观察本地延迟,用 SLOWLOG GET 10 查看慢命令,用 redis-cli --bigkeys 定位大 key。
修复策略要区分“临时缓解”和“根治”。临时可以增加从节点数量做读扩展、把大 key 拆分、把 appendfsync 调整为 everysec;根治则要优化业务写入模型,避免单 key 过大,必要时对主节点做分片。需要注意的是,延迟指标应设置告警阈值,例如 offset 差值超过 10MB 或 master_last_io_seconds_ago 超过 10 秒即触发告警。
三、主从数据不一致:切换前必须确认
数据不一致通常有三种来源:一是复制延迟导致从节点天然落后;二是主节点发生了未同步的写入后宕机,这部分数据在从节点上不存在;三是人为误操作,例如在从节点上执行了写命令(replica-read-only no 时),造成主从分叉。第三种最危险,因为从节点一旦接受本地写入,后续复制流可能覆盖或冲突,导致数据状态难以预测。
验证一致性的实用方法是抽样比对。可以对关键 key 在主从分别执行 DEBUG OBJECT 或 OBJECT ENCODING,更严谨的做法是用 redis-cli --scan 抽样后比对 DUMP 结果。生产环境更推荐在业务低峰期用 redis-rdb-tools 或 redis-full-check 做全量校验。若发现从节点有本地写入,应尽快用 REPLICAOF 重新挂载并触发全量同步,而不是手工修补。
四、手动主从切换流程
当主节点故障且无法快速恢复时,需要手动把某个从节点提升为新主。手动切换的关键是“先确认、再提升、后改挂”,避免脑裂和数据丢失。以下流程以三节点为例:原主 10.0.0.11,从 10.0.0.12、10.0.0.13,计划提升 10.0.0.12。
- 确认原主状态。在 10.0.0.11 上尝试
PING,若已无响应,再在 10.0.0.12 上查看master_link_status,确认复制已断开。 - 选择数据最新的从节点。比较 10.0.0.12 和 10.0.0.13 的
slave_repl_offset,选 offset 更大的节点,减少数据丢失。 - 提升新主。在 10.0.0.12 执行
REPLICAOF NO ONE,该节点变为 master,停止接受旧主的复制流。 - 改挂其他从节点。在 10.0.0.13 执行
REPLICAOF 10.0.0.12 6379,使其复制新主。 - 验证。在新主执行
INFO replication,确认role:master且connected_slaves:1;在 10.0.0.13 确认master_link_status:up,并观察 offset 是否追平。 - 处理旧主。旧主恢复后不要直接启动为 master,应先以从节点身份挂到新主,确认数据同步后再决定是否切回。
maxmemory、持久化配置和 repl-backlog-size 是否与原主一致。最后给出一份切换后检查清单,便于现场快速核对:新主 role:master、从节点 master_link_status:up、主从 offset 差值小于阈值、业务读写正常、旧主已降级为从且不再接受写入。把这几个点固化成操作卡,可以显著降低手动切换的误操作风险。