hello云胜

技术与生活

0%

主从同步

第一次主从同步流程

image-20220113171749651

  1. 从库给主库发送 psync 命令,表示要进行数据同步,主库根据这个命令的参数 来启动复制。psync 命令包含了主库的 runID 和复制进度 offset 两个参数。

    runID,是每个 Redis 实例启动时都会自动生成的一个随机 ID,用来唯一标记这个实 例。当从库和主库第一次复制时,因为不知道主库的 runID,所以将 runID 设 为“?”。 offset,此时设为 -1,表示第一次复制

  2. 主库收到 psync 命令后,会用 FULLRESYNC 响应命令带上两个参数:主库 runID 和主库 目前的复制进度 offset,返回给从库。从库收到响应后,会记录下这两个参数。

    FULLRESYNC 响应表示第一次复制采用的全量复制,

剩下的阶段比较简单。

所以建议:

一个 Redis 实例的数据库不要太大,一个实例大小在几 GB 级别 比较合适,这样可以减少 RDB 文件生成、传输和重新加载的开销。

如果有多个从库,可以采用“主 - 从 - 从”复制模式。

主从断连恢复

从 Redis 2.8 开始,网络断了之后,主从库会采用增量复制的方式继续同步

当主从库断连后,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也 会把这些操作命令也写入 repl_backlog_buffer 这个缓冲区。

repl_backlog_buffer 是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己 已经读到的位置。

image-20220113172522671

要强调一下,因为 repl_backlog_buffer 是一个环形缓冲区,所以在 缓冲区写满后,主库会继续写入,此时,就会覆盖掉之前写入的操作。如果从库的读取速 度比较慢,就有可能导致从库还未读取的操作被主库新写的操作覆盖了,这会导致主从库 间的数据不一致。

注意这个runID

runID

每个redis实例在启动时候,都会随机生成一个长度为40的唯一字符串来标识当前运行的redis节点,查看此id可通过命令info server查看。

如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会更具offset偏移量之后的数据判断是否执行部分复制,如果offset偏移量之后的数据仍然都在复制积压缓冲区里,则执行部分复制,否则执行全量复制;

如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的redis节点并不是当前的主节点,只能进行全量复制;

每次重启runID会变,所以如果master宕机,再重启.按着这个逻辑,是需要进行全量同步的.

redis4.0部分同步优化

redis4.0新增两个复制id,通过info replication查看

image-20220113174115491

1
2
master_replid:e921804a4f45d1a4a85f33bc6cded39df82885da
master_replid2:0000000000000000000000000000000000000000

去对用的从节点看一下

image-20220113174908585

第一组:master_replid和master_repl_offset:如果redis是主实例,则表示为自己的replid和复制偏移量; 如果redis是从实例,则表示为自己主实例的replid1和同步主实例的复制偏移量。

第二组:master_replid2和second_repl_offset:无论主从,都表示自己上次主实例repid1和复制偏移量;用于兄弟实例或级联复制,主库故障切换psync。

redis在关闭时,把当前实例的repl-id和repl-offset保存到RDB文件中,

redis加载RDB文件,会专门处理文件中辅助字段(AUX fields)信息,把其中repl_id和repl_offset加载到实例中,分别赋给master_replid和master_repl_offset两个变量值,特别注意当从库开启了AOF持久化,redis加载顺序发生变化优先加载AOF文件,但是由于aof文件中没有复制信息,所以导致重启后从实例依旧使用全量复制!

从节点上报复制请求时,传master_replid和master_repl_offset

主节点判断这两个信息,不再判断runid

判断是否使用部分复制条件:如果从库提供的master_replid与master的replid不同,且与master的replid2不同,或同步的offset快于master; 就必须进行全量复制,否则执行部分复制。

也就是说如果现在的主从,两者之前都是某一个master的从,并且进行了同步.当之前的这个master宕机以后,两个从的一个升级未主,另一个在这种情况下只需要进行部分复制.

img

但是如果进行了主从切换,之前的主再重新起来.如果能从rdb中恢复master_replid,理论上来说应该是会进行部分同步,但是如果用的aof,丢掉了master_replid应该会全量同步.(待实验!!)