从零起步学习Redis || 第十章:主从复制的实现流程与常见问题处理方案深层解析
一、前言
Redis 的主从复制(Replication)是 Redis 高可用架构的基础之一。
通过复制机制,可以实现数据的冗余备份、读写分离、负载均衡,并为后续的哨兵(Sentinel)和集群(Cluster)提供支撑。
本文将从 Redis 的内部机制角度出发,深入分析主从复制是如何在底层实现的,包括核心流程、关键数据结构、协议交互和优化机制。
二、主从复制的整体流程概览
Redis 主从复制的整个过程可以分为 三个阶段:
建立连接阶段(主从握手)
数据同步阶段(全量复制或部分复制)
命令传播阶段(实时增量同步)
整体思想是:
从节点通过 psync 命令与主节点进行握手,完成一次性数据同步(RDB + backlog),然后实时接收主节点写命令,从而保持与主节点数据一致。
三、阶段一:主从握手(连接建立)
当一个从节点启动并配置主节点地址后
,会主动向主节点发起复制请求:
PSYNC ? -1
?:主服务器的ID,因为第一次连接不知道主服务器的Id,所以用?表示
-1:复制的进度
这条命令表示:
“我没有历史同步信息(第一次连接)”
“请告诉我该从哪里开始复制”
主节点收到 PSYNC
请求后,会做以下判断:
如果是第一次连接 → 返回
+FULLRESYNC <run_id> <offset>
(全量复制)如果 run_id 匹配且 offset 合法 → 返回
+CONTINUE
(部分复制)
关键点解释:
参数 | 说明 |
---|---|
run_id | 主节点实例的唯一标识符(每次重启会重新生成) |
offset | 主从之间同步的“命令流偏移量”,用于标记同步进度 |
PSYNC | Redis 复制协议的核心命令,用于协调全量或增量复制 |
四、阶段二:数据同步阶段
全量复制(Full Resynchronization)
当主节点发现从节点没有旧数据或偏移信息时,就会触发全量复制。
内部执行过程如下:
主节点执行
BGSAVE
创建后台子进程,生成当前内存数据的 RDB 快照;
主线程继续响应客户端请求;
所有新的写命令会暂存到 复制缓冲区(replication buffer) 中。
传输 RDB 快照
RDB 生成完毕后,主节点通过 socket 发送给从节点;
从节点清空现有数据;
从节点加载 RDB 文件,恢复数据。
发送 backlog 中的增量命令
主节点会将 RDB 生成期间积累的命令(在复制缓冲区(replication buffer)中)同步发送给从节点;
从节点执行这些命令,使数据状态追上主节点。
至此,第一次同步工作完成
优点: 保证数据完整
缺点: 对带宽和磁盘开销大,耗时较长
五、阶段三:命令传播阶段(实时同步)
一旦主从数据完全一致,主节点会持续地将新的写命令实时发送给从节点。(基于TCP长连接)
主节点的行为:
每当执行一个写操作(如
SET key value
):写入主节点内存;
将命令追加到复制缓冲区;
异步发送给所有从节点。
从节点的行为:
从节点以“伪客户端”的身份接收主节点发来的命令;
解析后执行这些命令,更新自身数据;
定期向主节点汇报自己的复制偏移量(offset)。
这个阶段是异步的:
主节点不会等待从节点确认即可向客户端返回结果。
因此可能存在数据丢失的风险(主节点宕机但命令尚未传播到从节点)。
六:问题:TCP连接断开一段时间后,又连接上了怎么办?
答:重新连接后,从节点psync主节点,开始增量复制这段时间的数据,因为主节点在传播命令时,还会把命令写入repl backlog buffer(环形缓存区,默认1m),从节点在psync会传递一个slave repl offset给主节点,主节点比较自身的master repl offset与s-r-o,从r-b-b中发送命令给复制缓冲区(replication buffer),但由于这是一个环形缓存区,如果断联时间过长,会导致一些命令的覆盖,此时就只能全量复制。
六、核心数据结构与机制
Redis 在主从复制中维护了一系列核心数据结构,用于记录同步状态和命令流。
名称 | 作用 | 说明 |
---|---|---|
run_id | 主节点唯一标识 | 用于判断主节点是否重启过 |
offset | 命令流偏移量 | 每次写操作增加,用于同步进度 |
replication backlog buffer | 积压缓冲区 | 固定大小的循环缓冲区(默认 1MB),存储最近的命令流 |
replication buffer | 复制缓冲区 | 主节点为每个从节点单独维护的命令队列 |
PSYNC 命令 | 同步协调命令 | 实现全量与增量复制逻辑 |
client 结构体 | 主从连接对象 | 维护复制状态、缓冲区、偏移量等信息 |
七、复制中的辅助机制
1️⃣ ACK 反馈机制
从节点会定期向主节点发送:
REPLCONF ACK <offset>
表示“我已经同步到哪个偏移量”。
主节点通过该信息判断从节点延迟情况,并决定是否需要触发部分或全量复制。
2️⃣ 心跳机制(ping-pong心态检测机制)
主从之间会定期发送心跳包(PING/ACK),用于:
检测连接是否健康;
校准复制偏移;
保证命令传播的连续性。
3️⃣ 复制积压缓冲区(Backlog)优化
repl-backlog-size
默认 1MB,可根据网络稳定性与写入频率适当调整。
缓冲区越大,从节点掉线后越容易进行部分同步而非全量同步。
八、复制过程总结图(文字版)
从节点启动↓
发送 PSYNC ? -1↓
主节点判断 → FULLRESYNC(全量) / CONTINUE(部分)↓
[全量] 主节点执行 BGSAVE 生成 RDB → 传输给从节点↓
[部分] 从 backlog 发送缺失命令流↓
从节点加载 RDB 或执行增量命令 → 状态追平↓
主节点持续异步发送写命令(命令传播阶段)↓
从节点执行命令 + 汇报 offset
九、Redis 复制机制的特点与局限性
特性 | 优点 | 缺点 |
---|---|---|
异步复制 | 主节点性能高,延迟低 | 有数据丢失风险 |
部分同步 | 快速恢复中断连接 | 依赖 backlog 缓冲区大小 |
全量同步 | 确保一致性 | 对大数据量成本高 |
多从复制 | 支持一主多从 | 主节点网络压力大 |
十、结语
Redis 的主从复制机制虽然本质上是异步的,但其通过 PSYNC
协议、replication backlog buffer
、ACK 反馈机制等设计,实现了高效、可靠的复制能力。
理解其内部原理,不仅有助于我们调优高可用架构,也为深入掌握 Redis Sentinel 和 Cluster 打下了坚实基础。