redis的主从复制原理经历了多个版本的更新。
redis2.8之前的SYNC方案
命令:
SYNC
https://www.yuque.com/snailclimb/mf2z3k/ks9olb19hc9wse5k#5935f46a
存在的问题:
- slave加载RDB的过程中不能对外提供读服务
- slave和master断开连接后,slave重新连上master需要进行全量同步
redis2.8的PSYNC方案
命令:
PSYNC replicationid offset
PSYNC 解决了 slave 和 master 断开连接(如网络波动)之后需要重新进行全量同步的问题。不过,部分情况(比如 slave 突然宕机或者被重启)重连之后依然需要进行全量同步。(如果首次连接,也要全量同步)
怎么解决的?
slave 会记录 master 的运行 id (也就是 runid)和自己的复制进度/偏移量(slave_repl_offset)。master 也会记录自己写入缓冲区的偏移量(master_repl_offset),如果 runid 匹配的话,通过 slave_repl_offset 和 master_repl_offset 就可以确认 slave 缺少的数据是否在缓冲区中以及缺少的具体是哪一部分的数据。
注意:首次连接时slave还不知道master的runid
总结一下PSYNC有哪些情况还是需要进行全量同步?
- slave首次与master连接
- slave突然宕机或重启,runid和offset都丢失了
- master突然宕机或重启,新选出来的master的runid和offset都会变化。
run_id是啥
每个redis节点启动时会有个运行id,可以通过info server
查看
redis4.0的PSYNC 2.0方案
优化了【主从切换后runid和offset变化】导致需要全量同步的问题,在主从切换后,仍可以与新的master进行增量同步而不用全量同步。
如何实现?
舍弃了runid,使用replid和replid2
- 对于master来说,replid就是自己的复制id。没有发生主从切换前,replid2为空。发生主从切换之后,新的 master 的 replid2是旧 master (前一个自己同步的 master) 的 replid,在主从角色切换的时候会用到。
- 对于slave来说,replid 保存的是自己当前正在同步的 master 的 replid。replid2保存的是旧 master 的 replid,在主从角色切换的时候会用到。
还有两个偏移量相关的字段: - master_repl_offset:当前的复制偏移量
- second_replid_offset:没有发生主从切换前,second_replid_offset的值为-1;发生主从切换之后,新的master的second_replid_offset为旧master的复制偏移量。
replid和replid2用于判断发生主从切换之后,新的 master 和 slave 曾经属于同一个主库。如果属于同一个主库,可以进行增量同步的尝试。