什么是Redis 主从复制
Redis 主从复制是指把 Redis 主节点的数据同步到从节点的过程,使得主节点的数据和从节点的数据保持一致
Redis 主从复制原理
1. 主从复制初始化(Full Resynchronization)
当从节点首次连接到主节点或主从节点状态不一致时,会触发全量同步过程:
- 步骤1:从节点发起连接从节点启动时,通过发送
PSYNC
命令向主节点请求同步数据。PSYNC
包含从节点的replication offset
(偏移量,用于标记从节点的数据同步位置)和replica ID
(上次同步时的主节点 ID)。如果第一次发送不知道主节点 ID ,offset 第一次同步为-1 所以发送 psync ? -1 - 步骤2:主节点判断同步类型主节点根据
replica ID
和replication offset
判断是否可以进行增量同步。如果无法增量同步,主节点会响应FULLRESYNC
,并开始执行全量同步。 - 步骤3:主节点生成 RDB 快照主节点执行
bgsave
操作生成 RDB 快照文件,将当前内存数据快照化保存,同时将新写入的命令记录到replication buffer
中,确保全量同步期间不会遗漏新写入的数据。 - 步骤4:发送 RDB 文件主节点将生成的 RDB 文件发送到从节点。此过程是一个二进制传输过程,能够确保数据一致性。
- 步骤5:从节点载入 RDB 文件从节点接收到 RDB 文件后,载入到自己的内存中,完成数据的初始同步。
- 步骤6:发送复制缓冲区内容RDB 文件传输完成后,主节点将积累在
replication buffer
中的增量命令(即在 RDB 快照生成后产生的写操作)发送到从节点,以确保从节点数据与主节点完全一致。
2. 增量复制(Incremental Synchronization)
在主从完成全量同步后,会保持一个长连接,从节点进入增量复制阶段,即每次主节点有写操作时都会实时发送给从节点:
- 步骤1:主节点写操作传播主节点在执行写操作时,会将操作命令同时写入
replication buffer
和repl_backlog_buffer
(用于短时断连后快速恢复),并实时推送给所有从节点。 - 步骤2:从节点接收并执行从节点接收到增量命令后,立即在自己的数据集中执行相同操作,从而与主节点保持一致。
3. 断连后的数据同步(部分同步/断连恢复)
如果从节点与主节点因为网络故障等原因短暂断开,当它重新连接时会尝试进行部分同步,以避免全量同步的开销:
- 步骤1:从节点重新发送 PSYNC从节点重新连接后,会发送
PSYNC
命令,其中包含上一次复制的replica ID
和replication offset
。 - 步骤2:主节点检查同步偏移量主节点通过对比从节点的
replication offset
,检查repl_backlog_buffer
中是否有缺失的数据。若有,则进行部分同步,补齐缺失的增量命令;否则,主节点会要求从节点进行全量同步。 - 步骤3:增量命令补齐如果
repl_backlog_buffer
中有从节点缺失的命令,主节点会从偏移量对应位置开始,将缺失的数据发送给从节点,以便快速恢复同步。
Replication Buffer 和 repl_backlog_buffer 区别
Replication Buffer
- 作用:Replication Buffer 是 Redis 主节点为每个从节点(Replica)创建的缓冲区,用来缓存将要发送给从节点的数据。每个从节点都有一个独立的
replication buffer
。 - 用途:当主节点产生新的写操作时,这些操作会先存储在各个从节点的
replication buffer
中,等待传输到各个从节点。 - 发送过程:Redis 会根据从节点的网络情况,从
replication buffer
中将数据发送到从节点。如果从节点因为网络或负载问题暂时无法接收数据,Replication Buffer 会在主节点上暂时保留数据,确保从节点恢复后能接收到所有数据。 - 内存占用:由于每个从节点都有独立的
replication buffer
,如果从节点数量较多或从节点延迟较大,主节点的内存占用会显著增加。
Replication Backlog Buffer (repl_backlog_buffer
)
- 作用:
repl_backlog_buffer
是一个环形缓冲区,专门用于存储主节点最近的变更操作日志,是全局唯一的,与从节点数量无关。 - 用途:当从节点短时间内失去连接后重新连接到主节点时,可以从
repl_backlog_buffer
中快速获取自己缺失的数据,而无需进行完整的重同步(也就是避免了FULL RESYNC
)。 - 发送过程:如果从节点短暂断连并重新连接,主节点会检查该从节点的复制偏移量,从
repl_backlog_buffer
中找到自从节点最后接收的数据之后的所有操作并发送给从节点。 - 内存占用:
repl_backlog_buffer
的大小是固定的,不会随从节点数量的增加而增加,因此对内存的占用更可控。