在Redis中用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制另一个服务器,我们称呼被复制的服务器为主服务器,而对主服务器进行复制的服务器则被成为从服务器。
旧版复制功能的实现
Redis的复制功能分为同步和命令传播两个操作:
同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。
命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。
同步的步骤:
1)从服务器向主服务器发送 SYNC命令。
2)收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
3)当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB 文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行 BGSAVE命令时的数据库状态。
4)主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。
通信过程:
image.png同步过程
image.png命令传播
在同步操作执行完毕之后,主从服务器两者的数据库将达到一致状态,但这种一致并不是一成不变的,每当主服务器执行客户端发送的写命令时,主服务器的数据库就有可能会被修改,并导致主从服务器状态不再一致。
举个例子,假设一个主服务器和一个从服务器刚刚完成同步操作,它们的数据库都保存了相同的五个键 k1至 k5
如果这时,客户端向主服务器发送命令DEL k3,那么主服务器在执行完这个DEL命令之后,主从服务器的数据库将出现不一致∶主服务器的数据库已经不再包含键k3,但这个键却仍然包含在从服务器的数据库里面
image.png
为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作∶主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态。
image.png
旧版复制功能的缺陷
在 Redis中,从服务器对主服务器的复制可以分为以下两种情况∶
初次复制∶从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同。
断线后重复制∶处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连接重新连上了主服务器,并继续复制主服务器。
对于初次复制来说,旧版复制功能能够很好地完成任务,但对于断线后重复制来说,旧版复制功能虽然也能让主从服务器重新回到一致状态,但效率却非常低。
从服务器断线后重复制的过程
image.png从上图中我们可以看出,每次断线重复制都要生成全部键的RDB文件,然后发送给从服务器,其实需要同步的只是断线期间主服务器执行的写命令。上图是k10087、k10088、k10089三个键的数据。
新版复制功能的实现
为了解决旧版复制功能在处理断线重复制情况时的低效问题,Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操作。
PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式∶
其中完整重同步用于处理初次复制情况∶完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送 RDB 文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。
而部分重同步则用于处理断线后重复制情况∶当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。
从服务器断线重连后PSYNC的执行过程
image.png image.png鉴于复制篇幅有点长,关于部分重同步的细节,我们放到下一个小节
网友评论