redis主从数据同步的原理
数据同步原理
主从第一次同步是全量同步,但是如果slave重启后同步,则执行增量同步。
第一阶段
slave和master建立第一次同步的时候,需要执行replicaof命令,并且指定了master的ip和端口,slave和master连接一旦建立成功,slave就会向master发出请求来数据同步,然后master就会问slave是否是第一次来建立连接,如果slave不是第一次来的话,slave就代表已经有一部分master的数据了,如果slave是第一次来的话,master就会将完整的数据给slave,master在将完整的数据给slave之前,先将master的数据版本信息给slave,这样可以确保将来对版本的控制。在确定是第一次建立连接的时候,master就会将完整的信息给slave,master在做数据同步的时候它其实就是会执行bgsave命令,生成RDB。一旦执行bgsave命令,后台就会有一个独立的进程生成RDB文件,这样对主进程没有影响,主进程还是会执行用户的请求。RDB一旦生成,它里面记录了完整的内存信息发给slave(从节点),这个时候slave会先将它本地的数据清空,然后加载RDB的文件,这样就可以保证它和master的信息基本一致。
第二阶段
在主节点在发送内存给slave的期间执行主进程的信息,把这个时候的执行的命令存在replbaklog(内存缓存区)中,
所以RDB加上repl_baklog中执行的命令就是master的所有信息了。
第三阶段
将repl_baklog中的命令发送给slave,slave将master发送的repl_baklog里面的命令都执行一遍就可以保证它和master数据一致,如果后续再有命令发送过来,master也会将它保存在repl_baklog中,然后创建独立的进程发送给slave。
这里有一个问题,master如何得知salve是第一次来连接呢??
有几个概念,可以作为判断依据:
- Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
- offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。
如果slave和master的replid id不一致一定是第一次来。
总结
简述全量同步的流程
- slave节点请求增量同步
- master节点判断replid,发现不一致,拒绝增量同步
- master将完整内存数据生成RDB,发送RDB到slave
- slave清空本地数据,加载master的RDB
- master将RDB期间的命令记录在repl_baklog,并持续log中的命令发送给slave
增的是slave到master这之间的数据
只要slave和master的信息差距不要超过这个环的上限(存储上限),就永远可以同步信息
什么时候增量同步会失败?slave宕机了,但是master还是不停记录信息,结果超过了slave
注意:repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log增量同步,只能再次全量同步。
可以从以下几个方面来优化Redis主从就集群:
- 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
- Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
- 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
- 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力
下图中slave1执行命令时将id和端口设置成前面那个slave,而不是设置成master了
总结
简述全量同步和增量同步区别?
全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。
增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave
什么时候执行全量同步?
slave节点第一次连接master节点时
slave节点断开时间太久,repl_baklog中的offset已经被覆盖时
什么时候执行增量同步?
slave节点断开又恢复,并且在repl_baklog中能找到offset时