Redis 主从复制与哨兵机制详解:从原理到高可用实战
1. 引言
Redis 作为高性能的键值存储系统,在生产环境中常面临两大挑战:单点故障(一个节点宕机导致服务不可用)和读写压力(单节点无法承载高并发读请求)。为了解决这些问题,Redis 提供了主从复制(Master-Slave Replication)来实现数据冗余和读写分离,并进一步通过哨兵(Sentinel)实现自动故障转移,构建高可用的 Redis 服务体系。
本文将深入剖析主从复制的全量和部分同步原理、复制积压缓冲区的作用,以及哨兵如何通过监控、选主、故障转移来保障集群的持续可用。通过流程图和对比表格,帮助你彻底理解这些核心机制。
2. 主从复制基础
2.1 角色与特性
在 Redis 主从复制架构中:
- 主节点(Master):负责处理写请求,同时将数据变更异步复制到一个或多个从节点。
- 从节点(Slave):复制主节点的数据,可以处理读请求(实现读写分离),并在主节点故障时作为备选。
核心规则:
- 一个 Master 可以有多个 Slave
- 一个 Slave 只能有一个 Master(树状结构也是通过中间节点作为 Master 实现,但本质上每个 Slave 只有一个直接上游)
- 数据流向是单向的:只能从 Master 流向 Slave(写操作仅在 Master 执行,然后同步到 Slave)
2.2 解决的问题
| 目标 | 主从复制如何解决 |
|---|---|
| 高并发读 | 读写分离:Master 处理写,多个 Slave 处理读,提升整体吞吐量。 |
| 数据冗余 | 多个 Slave 持有数据副本,避免单点数据丢失。 |
| 高可用基础 | Master 宕机后,Slave 可被提升为新的 Master(需哨兵配合)。 |
3. 主从复制原理
主从复制分为全量复制和部分复制两个阶段。Redis 2.8 版本引入PSYNC命令,替代了旧版的SYNC,支持断线续传(部分复制),大幅提高了复制效率。
3.1 全量复制(Full Synchronization)
全量复制发生在以下场景:
- Slave 第一次连接 Master
- Slave 与 Master 断开时间过长,导致复制偏移量(offset)不在 Master 的复制积压缓冲区中
流程图
详细步骤
- 建立连接:Slave 根据配置的 Master IP 和端口,与 Master 建立 TCP 长连接。
- 发送 PSYNC:Slave 发送
PSYNC <replid> <offset>。若第一次连接,replid 为?,offset 为-1,表示请求全量复制。 - Master 响应:如果 Master 决定全量复制,返回
+FULLRESYNC <replid> <offset>,其中replid是该 Master 实例的复制 ID,offset是当前的复制偏移量。 - 生成 RDB:Master 执行
BGSAVE命令,生成当前数据快照的 RDB 文件。在此期间,所有新的写命令都会被记录到复制积压缓冲区(replication backlog buffer)中。 - 发送 RDB:Master 将 RDB 文件传输给 Slave。
- 清空并加载:Slave 清空自身旧数据,然后加载 RDB 文件,恢复数据状态。
- 发送缓冲区的命令:Master 将生成 RDB 期间缓存的写命令发送给 Slave。
- 执行命令:Slave 执行这些命令,使数据与 Master 最终一致。
- 持续同步:此后 Master 将新产生的写命令实时发送给 Slave,保持数据实时同步。
3.2 部分复制(Partial Synchronization)
当 Slave 与 Master 的网络断开后重连,如果 Master 的复制积压缓冲区中还保留了 Slave 断开期间丢失的写命令,则可以进行部分复制,避免全量 RDB 传输。
关键组件
- 复制积压缓冲区:Master 维护的一个固定大小的环形队列(默认 1MB),用于缓存最近向所有 Slave 发送的写命令。每个命令都有对应的偏移量(offset)。
- 复制偏移量(offset):Master 和每个 Slave 各自维护一个 offset,表示已复制的数据位置。
- Master 运行 ID(replid):Master 实例的唯一标识。Slave 会保存自己正在复制的 Master 的 replid。如果重连后 Master 的 replid 发生了变化(例如主从切换),则只能全量复制。
流程图
过程说明
- Slave 重连后,向 Master 发送
PSYNC <replid> <offset>,携带自身记录的 Master replid 和当前的复制偏移量。 - Master 检查:如果
replid与自身一致,并且offset仍然在复制积压缓冲区的范围内(即offset大于缓冲区最旧数据的位置),则返回+CONTINUE。 - Master 将缓冲区中从
offset开始的所有写命令发送给 Slave。 - Slave 接收并执行这些命令,完成数据追赶。
- 如果条件不满足,则进行全量复制。
💡
PSYNC的兼容性:从 Redis 4.0 开始,支持PSYNC2,进一步优化了故障转移后部分复制的场景。
4. 哨兵模式(Sentinel)
有了主从复制,当 Master 宕机时,虽然 Slave 可以继续提供读服务,但系统无法自动处理写请求,需要人工介入将某个 Slave 提升为 Master。哨兵(Sentinel)就是 Redis 提供的高可用解决方案:它可以监控主从节点的健康状态,并在 Master 故障时自动发起故障转移,选举新的 Master。
4.1 哨兵集群架构
哨兵本身也是一个分布式系统,通常部署多个实例(至少 3 个)组成集群,避免单点决策。
4.2 哨兵的核心工作流程
4.2.1 三个定时监控任务
每个哨兵实例会定时执行以下任务:
| 任务 | 命令 | 作用 |
|---|---|---|
| 每 10 秒 | INFO | 获取所有从节点信息,更新主从拓扑 |
| 每 2 秒 | SENTINEL HELLO频道 | 与其他哨兵交换信息,感知彼此存在 |
| 每 1 秒 | PING | 检查 Master、Slave、其他哨兵的存活状态 |
4.2.2 主观下线与客观下线
- 主观下线(SDOWN):当一个哨兵发现对 Master 的
PING没有在规定时间内(down-after-milliseconds)得到有效回复,就认为该 Master主观下线。 - 客观下线(ODOWN):当足够数量(
quorum)的哨兵都认为该 Master 主观下线后,就会将其标记为客观下线,并触发故障转移流程。
4.2.3 领导者哨兵选举
一旦 Master 被标记为客观下线,哨兵集群需要选出一个领导者来执行故障转移。选举基于Raft 算法的简化版本:
- 每个客观下线后的哨兵都向其他哨兵发送
SENTINEL is-master-down-by-addr命令,要求投票给自己。 - 哨兵遵循先到先得原则,为第一个请求投票。
- 获得超过半数(且至少
quorum)票数的哨兵成为领导者。 - 如果在规定时间内未选出,则重试。
📌特殊情况:即使哨兵集群只有一个节点,也能独立完成故障转移(因为单节点自然满足超过半数的条件),但这种部署存在单点风险,生产环境强烈建议至少 3 个哨兵实例。
4.2.4 故障转移(选举新 Master)
领导者哨兵执行以下步骤:
选举新 Master 的规则(依次比较):
- 优先级:
slave-priority(replica-priority)值越小优先级越高,为 0 表示不参与选举。 - 复制偏移量:offset 越大,表示数据越新,优先级越高。
- 运行 ID:如果以上都相同,选择 runid 最小的。
后续操作:
- 领导者将选中的 Slave 提升为 Master(发送
SLAVEOF NO ONE)。 - 向其他 Slave 发送命令,让它们复制新的 Master。
- 更新哨兵配置,当原 Master 恢复后,它会作为新 Master 的 Slave 加入。
5. 总结与最佳实践
5.1 主从复制 + 哨兵 = 高可用 Redis 集群
| 组件 | 主要作用 |
|---|---|
| 主从复制 | 数据冗余、读写分离、为高可用提供基础 |
| 复制积压缓冲区 | 实现部分复制,减少断线重连的数据传输量 |
| 哨兵 | 监控、自动故障转移、配置中心 |
5.2 实践建议
- 主从数量:每个 Master 挂载 1~3 个 Slave 即可,过多会增加 Master 的复制压力。
- 复制积压缓冲区:根据网络稳定性和写吞吐量调整
repl-backlog-size(默认 1MB,建议根据业务计算:每秒写入量 × 网络恢复预期秒数)。 - 哨兵部署:
- 至少 3 个实例,且应部署在不同物理机/容器上。
quorum一般设置为ceil(哨兵总数/2)。
- 客户端感知:应使用支持哨兵的客户端(如 Jedis、Lettuce 的
Sentinel模式),以便自动切换 Master 地址。 - 禁用危险命令:建议在 Master 上禁用
FLUSHALL、FLUSHDB,避免误操作导致所有 Slave 被同步清空。
5.3 全量与部分复制对比
| 维度 | 全量复制 | 部分复制 |
|---|---|---|
| 触发条件 | 首次连接、offset 太旧、replid 变化 | 网络短暂中断,offset 仍在缓冲区 |
| 数据传输 | RDB 文件 + 缓冲区命令 | 仅缓冲区中的增量命令 |
| 开销 | 高(磁盘 I/O、网络带宽) | 低 |
| 优化方向 | 增大 backlog、改善网络稳定性 | - |
6. 思考题
- 如果 Master 设置了
requirepass密码,Slave 应该怎么配置才能成功复制? - 哨兵选举领导者时,为什么需要超过半数的投票?
- 复制积压缓冲区设置过小会有什么后果?