Redis的全量同步是其主从复制机制的一部分,主要用于首次建立复制关系或当增量同步条件不满足时(例如从节点丢失了大量数据,无法通过复制偏移量定位差异)。全量同步涉及将主节点当前的所有数据一次性传输给从节点。以下是Redis全量同步在源码中的关键实现解析:
关键流程与源码位置
-
触发条件:
- 如前所述,全量同步通常在以下情况触发:新从节点首次加入、复制ID不匹配、复制偏移量不连续,或增量同步失败时。
- 判断逻辑位于
replication.c
中的replicationHandlePsyncCommand()
函数,通过比较从节点提供的复制ID和偏移量与主节点状态,决定是否执行全量同步。
-
执行BGSAVE:
- 一旦决定进行全量同步,主节点会调用
BGSAVE
命令来生成一份数据快照(RDB文件)。这个过程由rdb.c
中的rdbSave()
函数及其相关逻辑实现。 BGSAVE
通过fork()创建子进程来异步执行快照生成,确保主进程可以继续处理客户端请求。
- 一旦决定进行全量同步,主节点会调用
-
RDB文件发送:
- RDB文件生成后,主节点将其发送给从节点。这一过程涉及文件的读取和网络传输,具体实现在
replication.c
中,可能包括调用rioWrite()
函数将RDB数据写入网络连接。 - 在发送RDB之前,主节点会先发送一个特殊的握手协议,如
+FULLRESYNC <replication-id> <offset>
,告知从节点即将开始全量同步,并提供新的复制ID和偏移量。
- RDB文件生成后,主节点将其发送给从节点。这一过程涉及文件的读取和网络传输,具体实现在
-
从节点接收与加载:
- 从节点在收到
FULLRESYNC
响应后,开始接收并保存RDB文件。文件接收完成后,从节点会关闭旧的数据库,加载新RDB到内存中,这个过程同样在replication.c
中有相应逻辑。
- 从节点在收到
-
后续命令同步:
- RDB加载完毕后,从节点会发送
SYNC
命令(或在新版本中继续使用PSYNC
命令进入增量模式),主节点则会开始发送RDB生成期间积累的命令以及后续的新命令,确保数据完全同步。
- RDB加载完毕后,从节点会发送
关键数据结构与变量
- struct redisServer 中包含了与复制相关的全局变量,如正在进行的BGSAVE状态、复制ID等。
- struct redisClient 用于存储客户端连接信息,包括在全量同步中主从之间的通信状态。
注意事项
- 全量同步对系统资源消耗较大,尤其是网络带宽和磁盘I/O,因为它涉及到整个数据集的传输。
- 为了减少全量同步的频率,Redis提供了复制积压缓冲区来支持更频繁的增量同步。
- 在高负载场景下,可以通过配置
repl-diskless-sync yes
来启用无磁盘复制,减少磁盘I/O对主节点性能的影响,但这要求足够的内存来暂存RDB数据。
深入探索Redis全量同步机制,需深入研读rdb.c
中的RDB生成逻辑,以及replication.c
中主从交互、数据传输的相关代码。