redis系列

redis系列(五):主从同步

2020-05-30  本文已影响0人  范柏柏

就是从库和主库的数据要保持一致,主库的数据同步到从库的过程。

现有两个redis

127.0.0.1:12345 > slaveof 127.0.0.1:6379

这个时候,12345就是6379的从库了。

复制分为全量复制和增量复制。
全部复制触发在从库初始化的时候。
其他情况都是走的增量复制。增量就是主库每次修改的数据。

2.8之前的复制功能

redis复制功能分为同步(sync)和命令传播(command propagate)

同步

当从服务器知道自己是从服务器,并初始化的时候,开始执行同步。
过程:

  1. 从服务器想主服务器发送SYNC命令
  2. 收到SYNC命令的主服务器,执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
  3. 当主服务的BGSAVE命令执行完毕时,主服务器会将刚生成的RDB文件发送给从服务器。从服务器接收并载入这个RDB文件,将自己的数据更新至与主服务器执行BGSAVE命令时的状态。
  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些命令,将自己的数据库状态更新至主服务器当前所处的状态。
初始化同步过程.png
时间 主服务器 从服务器
T0 服务器启动 服务器启动
T1 执行 set k1 v1
T2 执行 set k2 v2
T3 执行 set k3 v3
T4 向主服务器发送SYNC命令
T5 接收到从服务器的SYNC命令,执行BGSAVE命令,创建包含k1、k2、k3的RDB文件,并使用缓冲区记录接下来执行的所有写命令
T6 执行 set k4 v4,并将这个命令记录到缓冲区
T7 执行 set k5 v5,并将这个命令记录到缓冲区
T8 BGSAVE命令执行完毕,向从服务器发送RDB文件
T9 接收并载入主服务器发来的RDB文件,获得k1,k2,k3三个键
T10 向从服务器发送缓冲分区保存的写命令set k4 v4和set k5 v5
T11 接收并执行主服务器发来的两个set命令,得到k4,k5两个键
T12 同步完成,现在主从服务器两者的数据库都包含了键k1,k2,k3,k4,k5 同步完成,现在主从服务器两者的数据库都包含了键k1,k2,k3,k4,k5

命令传播

当复制执行完了,以后主库的修改怎么做到的主从一致呢,这就要用到命令传播了。

当主库删除了k3,让从库也得删除k3。就要把del k3这个命令发送给从服务器。从服务器收到后,执行,这样就又一致了。完事。

老版本的缺陷

初次复制。没有问题。问题出在了断线后再次复制。看下过程:

时间 主服务器 从服务器
T0 主从服务器完成同步 主从服务器完成同步
T1 执行 set k1 v1 执行主服务器传来的 set k1 v1
T2 执行 set k2 v2 执行主服务器传来的 set k2 v2
... ... ...
T10085 执行并传播set k10086 v10086 执行主服务器传来的 set k10085 v10085
T10086 执行并传播set k10086 v10086 执行主服务器传来的 set k10086 v10086
T10087 主从服务断开连接 主从服务断开连接
T10088 执行set k10087 v10087 断线中,尝试重新连接主服务器
T10089 执行set k10088 v10088 断线中,尝试重新连接主服务器
T10090 执行set k10089 v10089 断线中,尝试重新连接主服务器
T10091 主从服务器重新连接 主从服务器重新连接
T10092 向主服务器发送SYNC命令
T10093 收到从服务器发来的SYNC命令,执行BGSAVE命令,创建包含k1值k10089的RDB文件,并使用缓冲区记录接下来执行的所有写命令
T10094 BGSAVE执行完毕,向从服务器发送RDB文件
T10095 接收并载入主服务器发来的RDB文件,获得k1至k10089
T10096 因为BGSAVE命令执行期间,主服务器没有执行写命令,所以不会发送缓冲区的写命令
T10097 主从服务器再次完成同步 主从服务器再次完成同步

问题就在T10093。他把所有的数据都放RDB传给从服务器了。从服务器k1至k10086都是有的。不用在来一遍。所以新版本复制功能就出来的,主要原则是引入了offset。

2.8之后的复制功能

2.8之后的同步命令不是SYNC了,而是PSYNC。

PSYNC分两种:

时间 主服务器 从服务器
T0 主从服务器完成同步 主从服务器完成同步
T1 执行 set k1 v1 执行主服务器传来的 set k1 v1
T2 执行 set k2 v2 执行主服务器传来的 set k2 v2
... ... ...
T10085 执行并传播set k10086 v10086 执行主服务器传来的 set k10085 v10085
T10086 执行并传播set k10086 v10086 执行主服务器传来的 set k10086 v10086
T10087 主从服务断开连接 主从服务断开连接
T10088 执行set k10087 v10087 断线中,尝试重新连接主服务器
T10089 执行set k10088 v10088 断线中,尝试重新连接主服务器
T10090 执行set k10089 v10089 断线中,尝试重新连接主服务器
T10091 主从服务器重新连接 主从服务器重新连接
T10092 向主服务器发送PSYNC命令
T10093 向从服务器返回+continue回复,表示执行部分重同步
T10094 接收+continue回复,准备执行部分重同步
T10095 向从服务器发送set k10087 v10087、set k10088 v10088、set k10089 v10089三个命令
T10096 接收并执行主服务器传来的三个set命令
T10097 主从服务器再次完成同步 主从服务器再次完成同步

部分重同步由三个部分构成

复制偏移量

一张图你就明白了


初始化状态.png 正常情况.png A掉线了.png

复制积压缓冲区

复制积压缓冲区是一个由主服务器维护的一个固定长度,先进先出队列。默认大小1MB。

在命令传播过程中,主库的过程:


命令传播.png

当从服务器连接上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对服务器进行何种同步操作:

回到刚刚断线重连表格的那个例子:

  1. 当从服务器A重连后,向主服务器发送PSYNC命令,报告自己的复制偏移量为10086

  2. 主服务器收到从服务器的PSYNC命令以及10086偏移量之后,主服务器将检查偏移量之后的数据是否还存在与复制积压缓冲区中,结果发现仍然存在,于是想从服务器发送+continue回复,表示以部分同步模式来进行。

  3. 接着主服务器会将复制积压缓冲区10086偏移量之后的所有数据(10087至10119)都要发送发给给从服务器。

  4. 从服务器接收到这33字节的缺失数据,就可以回到与主服务器一致的状态。

服务器运行ID

不管主从,服务器启动时,都会生成一个ID。

当主从初次复制的时候,从库会保存自己主库的ID。

当从断线并重新连上一个主服务器,从服务器会把上次复制的主服务器ID,发送给当前的主库。主库收到之后会判断:

如果在传输过程中,数据丢了怎么办

主库给从库发送10087至10119这段偏移量的所有数据,但网络问题丢了。在从库想主库每秒发送心跳的时候,心跳包中会包含从库的offset,如果不一样,把差掉的补发。(2.8之前没有这个功能)。

知识点

当从库接收主库的全量RDB文件。在载入RDB文件的时候,从库是不可用的

上一篇 下一篇

猜你喜欢

热点阅读