主从与哨兵
高可用的第一层是主从复制(数据冗余),第二层是哨兵(自动故障转移)。面试主线:复制怎么工作、哨兵怎么选主、脑裂怎么防。
主从复制
主从复制拓扑
同步过程(2.8+ 的部分重同步):
- 从库发
psync,带主库 runid 和复制偏移量 - 主库判断能增量:从 repl_backlog 缓冲区发缺失的命令
- 不能增量(首次或 backlog 溢出):全量同步,主库 bgsave 生成 RDB 发给从库,从库加载后再补缓冲期的增量命令
- 复制是异步的:主库写成功就返回,从库延迟取决于网络
- 从库默认只读,读写分离时注意延迟,强一致读要读主库
- 全量同步是昂贵的:大实例 RDB 传输占带宽,从库加载阻塞
哨兵:自动故障转移
哨兵(Sentinel)解决主库挂了没人干活的问题。三个职责:
| 职责 | 说明 |
|---|---|
| 监控 | 定期 PING 所有主从,判断存活 |
| 自动故障转移 | 主库挂了,选一个从库升主 |
| 通知/配置中心 | 通知客户端新主地址,Redis 6.2 的客户端缓存可订阅切换 |
下线判定:
- 主观下线:单个哨兵联系不上(可能只是网络抖动)
- 客观下线:多数哨兵(quorum)都认为挂了,才真正判定主库下线
选主:客观下线后,哨兵集群用 Raft 风格的投票选出 leader 哨兵,由它执行故障转移:从从库中选新主(优先级高、复制进度新的优先),其余从库改挂新主。
部署要求:哨兵至少 3 个(奇数),防止哨兵自己脑裂(1 个哨兵挂了就失去 quorum)。
脑裂与数据丢失
主库网络分区时可能产生脑裂:旧主还在写(客户端没感知),哨兵已把从库升为新主。分区恢复后旧主被降为从库,分区期间写的数据丢失。
缓解配置:
min-replicas-to-write:主库至少要有 N 个从库连接才接受写,从库失联就拒绝写,缩小丢失窗口min-replicas-max-lag:从库延迟超限也拒绝写
Redis 高可用的诚实结论:哨兵保证可用性(RTO 秒级),不保证数据不丢(异步复制)。要 RPO=0 需要同步复制方案或换共识存储。
面试追问
- 全量同步和增量同步? 首次或 backlog 溢出全量(RDB + 缓冲增量),正常增量(repl_backlog 补差)
- 主从复制是同步的吗? 异步。主库写成功即返回,从库可能落后。强一致读读主库
- 主观下线和客观下线的区别? 主观是单个哨兵的判断,客观是 quorum 多数确认。防止单点误判
- 哨兵怎么选新主? 哨兵集群先 Raft 选 leader,再从库中按优先级和复制进度选
- 脑裂怎么防? min-replicas-to-write 让旧主失联时拒绝写。本质是可用性和一致性的取舍