Redis-主从同步原理
主从节点建立连接
- 客户端发送命令slaveof master-IP master-PORT
- 启动服务时加上参数 redis-service -slaveof master-IP master-PORT
- 配置文件中加上配置参数 slaveof master-IP master-PORT
使用上述命令建立连接后,会通过socket连接发送心跳,保持连接
主从复制
全量同步:主节点生成RDB文件,发送给从节点进行数据同步,然后将生成RDB文件时保存到缓冲区的命令发送给从节点。简单来说,全量同步达到的目的就是使主节点和从节点的数据状态一致
命令传播同步:在全量同步后,主节点新产生的命令会通过命令传播给从节点
redis 2.8 版本之前
时间 | 主节点 | 从节点 |
---|---|---|
T0 | 主从建立连接 | |
T1 | 从节点发送SYNC命令 | |
T2 | 主节点执行bgsave命令开始生成RDB文件 | |
T3 | 主节点执行set k1 v1 命令 | |
T4 | 主节点生成RDB文件结束,并发送给从节点 | |
T5 | 主节点发送 | 从节点接收RDB文件并读取文件 |
T6 | 主节点将T3时间段内积压的命令发送给从节点 | |
T7 | 从节点同步缓冲区的命令 | |
T8 | 主节点执行set k2 v2 命令 | 执行主节点发送过来的set k2 v2 命令 |
T9 | 主节点与从节点断开连接 | |
T10 | 重复上述步骤 |
上面表格中,T2-T7 属于全量同步,T8属于命令传播同步
- [问题1:主从由于网络等问题而断开连接,那个下次连接后,还会从头开始(全量同步+命令传播同步),耗费性能 ]
redis 2.8 版本及之后
redis 2.8版本及以后的版本为了解决问题1出现的情况,增加了部分同步功能。
部分同步功能
实现部分同步,主从节点需要记录三个信息
- 复制积压缓冲区(主节点)
复制积压缓冲区是一个先进先出的环形队列,默认大小是1M。当主节点没有从节点连接时,主节点是不会生成缓冲区的,只有当有从节点连接过时,主节点才会创建缓冲区并且在执行命令的时候,也会将命令放入到缓冲区中。
- 运行ID(从节点记录主节点的ID)
每个Redis服务在启动时,都会生成一个40位随机的十六进制字符当作该节点的运行ID,当主从关系建立后,主节点会将自己的运行ID发送给从节点,从节点保存主节点运行ID。
- 复制偏移量(主从节点都需要记录偏移量)
主节点将命令发送给从节点时,主节点和从节点都会将自己节点的偏移量加上当前命令的偏移量。当主从节点断开连接,再次重连后,通过比较主节点和从节点的复制偏移量来确定是否需要同步。
部分同步功能
时间 | 主节点 | 从节点 |
---|---|---|
T0 | 主从节点第一次建立连接 | |
T1 | 同Redis2.8以前的版本,并且将自己的运行ID发送给从节点,并且同步复制积压缓冲区和复制偏移量 | 同Redis2.8以前的版本,并且保存主节点运行ID,同步自己的复制偏移量 |
T2 | 主从节点由于网络等问题断开连接 | |
T3 | 主节点执行set k1 v1 命令,同步命令到复制积压缓冲区和增加复制偏移量 | |
T4 | 从节点连接,发送PSYNC命令,下面会详细解释PSYNC命令 | |
T5 | 主节点接收PSYNC命令,开始判断是否可以部分同步 | |
T6 | 如果可以部分同步,将未发送给从节点复制积压缓冲区的命令发送给从节点 | |
T7 | 从节点同步命令 | |
T8 | 如果不能部分同步,则执行全量同步 |
PSYNC命令
Redis2.8版本之后,使用PSYNC命令替换了SYNC命令,PSYNC中的P代表的是部分的意思
PSYNC runid offset
- runid:主节点ID,标识Redis主节点身份
- offset:从节点最后接收命令的偏移量,redis服务器数据的长度
- 步骤1,如果从节点第一次连接,发送的命令 PSYNC ?-1;如果不是第一次连接,发送的命令 PSYNC runID offset
- 步骤2,主节点通过从节点发送的PSYNC 命令中的是否有runID判断是否是第一次同步
- 步骤3,通过比较主节点和从节点的复制偏移量,如果相同,则不需要同步;否则,根据从节点的复制偏移量查看复制积压缓冲区中的数据是否存在,如果存在,则进行部分同步;否则,进行全量同步
PSYNC 升级版
Redis4.0版本之后,Redis对PSYNC命令进行了升级。
因为Redis2.8版本虽然添加了runId用来区分全量同步和部分同步,但是没办法解决主从节点由于网络等问题导致的主从节点切换而带来的同步问题,因为主从节点切换后,runId也会变化,这样2.8版本的情况下还是会进行全量同步。所以升级版的PSYNC命令解决了上述问题
如上图所示:
-
master_replid
-
master_repl_offset
master_replid代表的自己的当前主节点的id,master_repl_offset代表的是自己的复制偏移量。
-
master_replid2
-
second_repl_offset
master_replid2代表的自己的上一个主节点的id,second_repl_offset代表的是自己的上一个主节点同步时的复制偏移量。如果,主从节点切换,那么新选举出的主节点的master_replid如果与从节点的master_replid和master_replid2都不一致或者从节点的任何一个复制偏移量快于主节点,那么就会进行全量同步。
以上是本人的学习总结,如有不对,请轻喷