集群与故障转移排查

主从和 Cluster 的故障有一个共同特征:应用侧只看到零星超时和报错,真正的问题却在拓扑里。本章按“先看复制链路,再看集群状态,最后看客户端拓扑与重试”的顺序给出排查方法,并解释 MOVED、ASK、CLUSTERDOWN 这些报错背后的机制。

两个排查入口

部署形态排查入口常用命令
主从 / 哨兵INFO replication 加哨兵日志redis-cli info replicationredis-cli -p 26379 sentinel masters
ClusterCLUSTER INFOCLUSTER NODESredis-cli cluster inforedis-cli -c cluster nodesredis-cli --cluster check 10.0.0.11:6379

redis-cli -c 的作用是收到 MOVED 后自动跟随到正确节点,用它执行命令可以验证“客户端跳转这条路是否通”,排查拓扑本身则两种写法都行。

主从:先看复制链路

redis-cli info replication
# role:master
# connected_slaves:2
# slave0:ip=10.0.0.12,port=6379,state=online,offset=123456789,lag=0
# master_repl_offset:123456999
redis-cli -h 10.0.0.12 -p 6379 info replication | grep -E 'master_link_status|master_last_io_seconds_ago|slave_repl_offset|slave_read_only|master_sync_in_progress'
字段正常值异常含义
master_link_statusupdown:复制链路已断,从库数据在不断变旧
master_last_io_seconds_ago小于 1持续增大:网络问题或主库繁忙导致心跳滞后
slave_repl_offset 与主库 master_repl_offset 的差小于 1MB差值持续扩大:复制跟不上,大写入、带宽不足或从库自身慢
slave_read_only1为 0 表示从库可写,存在脑裂与数据分叉风险
master_sync_in_progress0长期为 1:正在全量同步,此期间从库不可用
lag(主库视角的 slave 项)0大于 1 且持续:该从库已在拖后腿
主库 rdb_bgsave_in_progress0频繁为 1 说明全量同步风暴在进行

全量同步风暴

成因链:从库断线时间超过 repl-backlog 覆盖范围 → 重连只能全量同步 → 主库 fork 并生成 RDB → 网络被打满、主库延迟飙升 → 应用超时 → 更多从库被判失联。

redis-cli config get repl-backlog-size       # 建议按“写入速率 × 最长断线时间”估算
redis-cli config get 'client-output-buffer-limit'
redis-cli info stats | grep -E 'sync_full|sync_partial_ok|sync_partial_err'
  • sync_full 持续增长而 sync_partial_ok 不增长:说明增量复制(PSYNC)几乎没成功过,重点查 repl-backlog-size 与网络稳定性。
  • client-output-buffer-limit replica 256mb 64mb 60:全量同步期间从库缓冲超过硬限制会被主库直接断开,表现就是“反复全量同步”。盲目调大能缓解症状,但根因往往是带宽不足或从库消费太慢。
  • 多个从库同时重建会叠加压力:错峰重建,必要时临时把读流量从这些从库摘掉。

Cluster:CLUSTER INFO 判读

redis-cli cluster info
redis-cli -c cluster nodes
redis-cli --cluster check 10.0.0.11:6379
redis-cli cluster slots | head
字段期望值异常含义
cluster_stateokfail:存在未覆盖的槽或失联主节点超过阈值,客户端所有写请求报 CLUSTERDOWN
cluster_slots_assigned16384小于 16384 表示有槽没分配,集群整体不可用
cluster_slots_ok / cluster_slots_pfail / cluster_slots_fail16384 / 0 / 0pfail 或 fail 大于 0 说明有槽处于疑似失败或失败状态
cluster_known_nodes等于真实节点总数多于实际:有僵尸节点没摘除;少于实际:节点未完成握手
cluster_size等于主节点数量不一致说明主从角色或拓扑配置混乱
cluster_stats_messages_sent/recv平稳增长增长异常高说明 gossip 消息风暴,通常是节点过多或网络抖动
CLUSTER NODES 中的 fail? / fail 标记出现标记的节点需要立刻确认进程与网络

常见报错与成因

报错成因处理
MOVED 1234 10.0.0.12:6379槽已归属其他节点,客户端未刷新拓扑客户端开启集群模式;排查是否用单机地址直连做了代理
ASK 1234 10.0.0.12:6379槽正在迁移中,需要先发 ASKING 再执行客户端需支持 ASK;长期出现说明迁移卡住,检查迁移进度
CLUSTERDOWN The cluster is down有槽未覆盖,或多数主节点失联先恢复节点与网络,再处理槽分配;不要在槽未覆盖时写入
CROSSSLOT Keys in request don't hash to the same slot一条命令涉及多个 key 但不在同槽用 hash tag 强制同槽(如 {user:1}:name),或拆成多条命令
TRYAGAIN Multiple keys request during rehashing多 key 命令落在迁移窗口内客户端重试并带退避
BUSY Redis is busy running a scriptLua 脚本执行超过 lua-time-limit拆短脚本;必要时 SCRIPT KILL(未写过数据时可用)

哨兵(Sentinel)排查

redis-cli -p 26379 sentinel masters
redis-cli -p 26379 sentinel sentinels mymaster
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
字段正常异常含义
flagsmaster出现 s_downo_down 说明哨兵认为节点已失联
num-slaves / num-other-sentinels与部署数量一致数量不符说明节点未注册或配置写错了地址
quorum奇数且小于哨兵总数quorum 过大时永远凑不齐票数,故障转移不会触发
哨兵实例数奇数,且至少 3 个哨兵为偶数时,网络分区容易产生两个主库(双主)

哨兵切换主库后,应用侧会看到连接被重定向或短暂报错。客户端必须支持哨兵模式并订阅 +switch-master 事件自动刷新主库地址,否则切换完成后仍会连到旧主库,表现为“只读实例上写入失败”。

故障转移期间的超时与重试

  • cluster-node-timeout 默认 15000ms。调小能加快故障转移,但网络抖动时更容易误判主节点失联;同机房内网建议 5000 ~ 10000,跨机房要大一些。
  • 客户端必须同时具备:连接超时、命令超时、有限重试(例如 2 次)、指数退避、拓扑自动刷新。缺任何一项都会在故障转移的几十秒里产生大量无效请求。
  • 无脑重试会把故障期的流量放大 2 ~ 3 倍,直接把幸存节点压垮,这是 Redis 集群最常见的二次故障。
  • 读写分离要区分两类请求:“读旧数据可接受”的走从库,“必须最新”的走主库(例如刚下单后的订单详情)。

脑裂与数据丢失窗口

场景现象代价
主从断开但主库继续接受写入切主后旧主的数据被丢弃断开期间的写入全部丢失
从库被配置为可写双主写入,数据分叉需要人工比对与修复
未设置 min-replicas-to-write主库在没有健康从库时仍接受写入故障转移后必然丢数据
哨兵/Cluster 判定延迟过大转移迟迟不触发,期间持续报错可用性下降

建议设置 min-replicas-to-write 1min-replicas-max-lag 10:用少量可用性换取不丢数据,前提是业务能明确说清“丢几秒数据是否可以接受”。说不清就不要打开这个开关。

处置与预防清单

  • 从库延迟大:先看是网络带宽还是从库自身慢命令,从库同样会被大 key 拖慢;必要时从读负载均衡中摘除。
  • 全量同步风暴:错峰重建、调大 repl-backlog-size、临时减少非必要订阅与从库数量。
  • 集群状态 fail:先确认节点进程与网络连通性,再处理槽;redis-cli --cluster fix 可用于修复槽覆盖,但执行前先备份拓扑信息。
  • 预防:复制延迟、节点状态、槽覆盖情况、cluster_state、故障转移次数全部纳入告警,并每季度演练一次故障转移。

小结:主从问题看 master_link_status、心跳时间与 offset 差,重点防全量同步风暴;Cluster 问题看 cluster_state、槽覆盖与节点数,MOVED/ASK/CROSSSLOT 分别对应拓扑未刷新、迁移进行中与多 key 跨槽;客户端必须做到有限重试加拓扑自动刷新,并用 min-replicas-to-write 把脑裂导致的数据丢失窗口压到业务可接受范围。

笔记加载中…