主从第一次同步是全量同步:
- 主节点和从节点一次建立连接是从节点需要执行一个replicaof命令或者slaveof的命令,并且指定master的ip和端口,向master请求数据同步。
- master会判断是否是第一次同步,如果是第一次则会返回的数据版本信息
- 从节点会保存这些版本信息
- 主节点会将数据进行bgsave,生成快照RDB并发送给从节点,主节点还会将记录RDB期间的所有命令保存到内存缓冲区repl_baklog
- 从节点收到数据时清空本地数据,并将RDB文件加载到内存
- 主节点将缓冲区的repl_baklog记录的命令发送到从节点,从节点不断执行这些命令就能达到数据的同步,确保数据永远一致。
master如何判断slave是不是第一次同步数据呢?
- Replication Id: 简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid.
- offset:偏移量;随着记录repl_baklog中的数据增多而增大。slave完成同步也会记录同步的offset,如果slave的值小于master的offset,说明slave的数据落后于master,需要更新
因此slave做数据同步,必须向master声明自己的offset和replication id,master才可以判断到底需要哪些数据。
总结全量同步的流程:
- slave节点请求增量同步
- master节点判断replid,发现不一致,拒绝增量同步,使用全量同步
- master将完整数据生成RDB,发送RDB到slave
- slave清空本地数据,加载RDB文件
- master将RDB期间产生的命令记录在repl_baklog,并持续性的将repl_baklog发送到slave
- slave接收到这些命令,保持与master数据同步。
主从第一次同步是全量同步,如果slave重启后同步,就会执行增量同步:
repl_baklog的容量是有上线的,写满后会覆盖最早的数据。如果slave断开的时间太久,导致尚未备份的数据被覆盖(offset会标记repl_baklog中备份的数据),就无法做增量同步,只能去做全量同步
可以从以下几个方面来优化Redis集群:
- 在master配置文件中配置repl-diskless-sync yes启用无磁盘复制(使用网络传输,对网络传输速度要求高点),避免全量同步时的磁盘IO。
- Redis单点上的内存占用不要太大,减少RDB导致的过多磁盘IO。
- 适当提高repl_baklog的大小,发现salve宕机时尽快实现故障恢复,尽可能避免全量同步。
- 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从链式结构,减少master压力。