本文总结:
1. 主从包括那些机制?包括三个阶段
- 第一次复制通过全量复制,全量复制完成之后(psync + RDB文件+repl_buffer);
- 命令传播阶段(通过长连接+repl_buffer保证 命令顺序性+ repl_backlog_buffer 实现数据补发);
- 恢复断连阶段增量同步(psync +repl_backlog_buffer )。redis 2.8之前和全量同步类似,通过psync代替sync实现增量同步。
2. 命名传播阶段是否会出现:第一指令没有成功,第二个成功了?
通过repl_buffer保证master节点给slave节点命令的顺序性。
1 全量复制和增量复制
1.1 全量复制
slaveof命令执行全量同步流程如下:
- slave节点向master节点发送“psync ? -1” 命令。
- master收到psync命令之后返回 FULLRESYNC 告知 slave 将执行全量同步。
- master执行bgsave命令,Redis会fork出一个子进程在后台生成RDB文件,同时将同步过程中的写命令记录到replication_buffer中。
- master会把生成的RDB文件发送给slave。
- slave接收到RDB文件会将其装载入内存。
- master将记录在缓冲区replication_buffer的所有写命令发送给slave,slave对这些命令进行「重放」,将其数据库的状态更新至和master一致。
1.2 断连处理-增量复制
在Redis 2.8之前,如果因网络原因,主从节点复制中断,当再次建立连接时,还是会执行SYNC命令进行全量复制。效率较为低下。从Redis 2.8开始,引入了PSYNC命令代替SYNC命令来执行复制时的同步操作。PSYNC命令相比之前SYNC提供了增量复制。
注意: “PSYNC ? -1 ” 和SYNC作用相同,都是全量复制。
PSYNC通过repl_backlog_buffer实现增量复制,流程如下:
1、断连期间
主库将命令记录到repl_backlog_buffer,并更新master_repl_offset
2、断连恢复
STEP1 从库通过PSYNC <replication-id> <offset>,发送salve_repl_offset 到主库。
STEEP2 主库将salve_repl_offset和master_repl_offset之间的数据发送给从库,即断连之间的数据。
- repl_backlog_buffer是环形缓存区,如果断连时间过长,命令会被覆盖,此时会进行全量同步。
2 基于长连接的命令传播
解释下repl_backlog_buffer和replation_buffer两个缓存的区别?
- replation_buffer每个长连接独享一个,建立主从连接之后生成的。
- 全量复制过程中,解决RDB生成、传输和加载过程中增量写问题。
- 命令传播过程中,实现命令按顺序同步到从节点。
- relation_backlog_buffer所有长连接共享一个,redis服务初始化时候生成的。
- 恢复断连过程中实现增量复制。
- 命令传播过程中实现数据补发。
在命令传播阶段,一个写命令到master之后会更新两个buffer:
- repl_backlog_buffer追加写命令
- replation_buffer追加写命令
当主从库完成了全量复制,它们之间就会一直维护一个长连接,主库会通过这个长连接将后续陆续收到的写操作命令(replation_buffer中命令)发送给对应的从库,这个过程也称为基于长连接的命令传播,使用长连接的目的就是避免频繁建立连接导致的开销。
2.1 命令传播如何保证顺序性
假设,当前主节点的master_repl_offset为1000,如下两个命令顺序达到主库:
- 命令1 -> 保存到缓存repl_backlog_buffer (200个字节)&&更新master_repl_offset 1200 -》 异步发送命令给从节点offset。
- 命令2 -> 保存到缓存repl_backlog_buffer(300个字节)&&更新offset 1500 -》 异步发送命令给从节点。
A: 在将命令1和命令2同步到从库过程中是否出出现: 命令1丢失了,命令2正常到从节点?即此时从节点offset为1300,然后从节点执行 REPLCONF ACK 1300,主节点如何处理?
Q: 不会出现这个问题。因为主节点往从节点发送命令是通过replation_buffer进行的。replation_buffer是每个从节点长连接独享一个,所以保证了master同步slave命令的有序性,如上面命令传播流程图。
2.2 心跳检测REPLCONF_ACK
在命令传播阶段,从节点间隔1秒向服务器发送一个“REPLCONF ACK{offset}” 命令。命令作用为:
- slave上报资损复制偏移量,检查是否存命令丢失。主节点判断master_repl_offset和slave_repl_offset是否一致性,不一致性就行数据补发操作。
- 判断master是否在线,如果超时则认为为master下线
- 将传播命令的长连接关闭;
- 等下次进行心跳检查,如果连接上,则触发增量同步PSYNC
数据补发和增量复制区别:
- 增量复制是主从连接断连,在连接恢复之后,从节点发送PSYNC <replication-id> <offset>进行触发的。
- 数据补发是在主从连接没有断连的情况下执行的。通过REPLCONF ACK{offset}触发。
3 拓扑结构- 主-从-从
为了降级master同步的压力,多采用“主-从-从”的复制模式。