Redis 主从复制与 Sentinel:从复制链路到自动故障切换(九)
Redis 真正进入高可用阶段时,不能把“复制”和“自动故障转移”分成两段完全独立的知识。复制负责让副本追上主库,Sentinel 负责在主库故障后判断是否切换、由谁切换、切到哪个副本,以及客户端应当去哪里找新主库。
系列导航:
- 上一篇:Redis 持久化:RDB、AOF 与恢复目标(八)
- 当前篇:Redis 主从复制与 Sentinel:从复制链路到自动故障切换(九)(本文)
- 下一篇:Redis Cluster:哈希槽、重定向与分片扩展(十)
复制先解决“副本怎么追上主库”
一个最基础的 Redis 高可用拓扑,至少有一个主库和一个副本:
应用写入
│
▼
主库
│ 异步复制流
▼
副本
主库处理写命令,副本接收并重放复制流。它解决的是“多一份近实时副本”的问题,但它本身并不负责:
- 主库故障后的自动提升。
- 客户端写入口自动切换。
- 故障时零数据丢失。
所以“已经有副本”和“系统已经高可用”之间,还差一整个控制平面。
全量同步、部分重同步和复制积压缓冲区
理解 Redis 复制,最关键的是三件事:replication ID、复制偏移量和复制积压缓冲区。
replication ID用来标识当前复制历史。- 复制偏移量用来标识复制流推进到了哪里。
- 积压缓冲区保存最近一段复制流,给短暂断线后的副本做续传。
首次建立复制关系时,副本通常要做一次全量同步:
- 副本发送
PSYNC。 - 主库判断当前没有可复用的复制历史。
- 主库准备 RDB 快照,同时把后续写命令暂存起来。
- 副本加载快照。
- 主库把快照期间积累的写命令补发给副本。
- 两端进入持续复制阶段。
如果副本只是短暂断线,重连时会带上自己记录的 replication ID 和偏移量。只要主库确认复制历史没变,而且缺失那段复制流还在积压缓冲区里,就可以做部分重同步,只发送断线期间缺失的部分,而不需要重新传整份数据集。
这也是 repl-backlog-size 真正该按业务写入速率来估算的原因。它不是越大越高级,而是要覆盖你希望副本可以容忍的断线时间窗口。
Redis 复制一直是异步复制
复制链路最重要的边界,是它默认不会把“副本已经确认收到”作为主库给客户端返回成功的前提。
这会形成一个很现实的风险窗口:
客户端收到写入成功
│
├─ 主库已执行
└─ 副本尚未收到
如果此时主库故障,而新的写主又从副本里选出来,那么这段还没来得及复制过去的写入就可能丢失。WAIT 能让单个客户端在当前连接上等待一定数量副本确认偏移量,但它不是把 Redis 复制改造成强一致协议,也不能替代完整的故障域设计和持久化设计。
因此,Redis 复制解决的是“尽快把数据传播到副本”,不是“任何故障下都严格不丢数据”。
Sentinel 负责把复制链路变成自动故障转移闭环
有了复制以后,系统仍然要回答四个控制面问题:
- 主库是真的故障了,还是某个节点自己的网络抖动?
- 由哪个 Sentinel 来主持这一轮故障转移?
- 哪个副本最适合被提升成新主库?
- 客户端之后应该去哪里找新的主库地址?
Sentinel 的职责正好覆盖这些点:
- 监控主库、副本和其他 Sentinel 的可达性。
- 通过逻辑主库名做服务发现。
- 在满足条件时协调故障转移。
- 在切换完成后把新主库信息暴露给客户端。
它不保存业务数据,也不代理 Redis 请求。应用最终还是直接连 Redis,只是在建立连接或故障恢复时,先向 Sentinel 查询“当前主库是谁”。
SDOWN、ODOWN、quorum 和多数派不是一回事
Sentinel 不会因为一个节点单方面超时就立刻提升副本。它把故障判断分成两层:
SDOWN:某个 Sentinel 在自己的视角里,连续一段时间联系不到主库。ODOWN:达到配置的quorum后,多个 Sentinel 对主库故障形成客观判断。
但形成 ODOWN 还不等于能立刻执行故障转移。因为还要再解决一个问题:谁来主持这一轮切换。这个时候依赖的是 Sentinel 多数派授权,而不是单纯的 quorum。
可以把两者记成:
quorum决定“大家是否同意主库可能真的坏了”。- 多数派决定“谁有权在这一轮真正动手切换”。
这也是为什么三 Sentinel、quorum 2 是最常见的最小可用拓扑。一台 Sentinel 失联时,剩余两台仍有机会完成判断和授权;只剩一台时,即使它看得到副本,也不应该独自完成自动故障转移。
Sentinel 会怎么选出新主库
当某个 Sentinel 获得本轮多数派授权后,它会从可晋升的副本里挑一个最适合成为新主库的候选者。筛选时通常会考虑:
replica-priority,值越小优先级越高,0表示不参与晋升。- 副本复制偏移量是否足够新,谁离旧主库最近。
- 运行 ID 等稳定排序字段,用于在条件接近时打破平局。
然后故障转移大致按下面的顺序推进:
- 把目标副本提升为新主库。
- 等待它角色切换生效。
- 让其他副本转向跟随新主库。
- 更新 Sentinel 内部维护的主库地址和纪元信息。
- 对外返回新的主库发现结果。
- 旧主库恢复后,将其收编为当前主库的副本。
你可以把整条链路理解成:复制提供数据连续性,Sentinel 提供角色重组和写入口切换能力。两者合在一起,才构成单主 Redis 的自动故障转移闭环。
客户端真正接入时要注意什么
Sentinel 成功切换,不代表应用就会自动跟上。要真正完成闭环,还要满足三个前提:
- 客户端支持 Sentinel 模式,并配置多个 Sentinel 地址与逻辑主库名。
- 应用没有把旧主库地址硬编码在配置里。
- 连接池、重连策略和认证信息能在主库切换后正确更新。
实际排查时,最常用的两个入口通常是:
redis-cli INFO replication
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
前者看主库、副本和复制偏移量,后者看 Sentinel 当前认定的写入口。只盯其中一边,很容易误判“复制明明正常,为什么业务还是没恢复”。
一条够用的线上检查清单
如果你希望把 Redis 单主高可用看得更稳,至少要固定检查下面这些问题:
- 副本是否真的能在短暂断线后做部分重同步,而不是频繁退回全量同步。
- 积压缓冲区大小是否匹配写入速率和网络波动窗口。
- Sentinel 的
quorum和部署位置是否避开同一故障域。 - 客户端是否真的通过 Sentinel 做主库发现,而不是只在文档里“支持”。
- 业务是否清楚接受异步复制下的丢失窗口边界。
- 旧主库恢复后是否有明确的重新纳管流程,而不是直接重新放流量。
把这些动作固定下来以后,“Redis 高可用”才不只是“我已经有副本,也已经起了几个 Sentinel”的表面状态。
本篇解决了什么:
- 把全量同步、部分重同步、复制积压和异步复制边界串成了一条链路
- 解释了
SDOWN、ODOWN、quorum和多数派授权在自动切换里各自负责什么 - 让复制与 Sentinel 不再拆成两篇独立拼图,而是形成完整高可用闭环