旧版主从复制的实现
Redis的复制功能分为 同步(sync)和 命令传播(command propagate)两个操作:
1)同步操作:作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。
2)命令传播:作用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。
同步操作
当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,即,将从服务器的数据库状态更新至主服务器当前所处的数据库状态,过程如下:
从服务器通过向主服务器发送SYNC命令来进行同步操作,SYNC命令的执行步骤如下:
1)从服务器向主服务器发送SYNC命令。
2)收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
3)当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接受并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
4)主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。
命令传播
同步操作执行完毕后,主从服务器两者的数据库状态达到了一致状态,但每当主服务器执行完客户端发送的写命令时,主从服务器的数据库状态将不一致。
为了让主从服务器再一次回到一致状态,主服务器需要对从服务器执行命令传播操作:主服务器将自己执行的写命令,发送给从服务器执行,使主从服务器保持一致状态。
旧版复制功能的缺陷
Redis 2.8以前,从服务器对主服务器的复制可以分为如下两种情况:
1)初次复制:从服务器以前没有复制过任何主服务器,或从服务器当前要复制的主服务器和上一次复制的主服务器不同。
2)断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连重新连接上了主服务器,并继续复制主服务器。
缺陷在于:断线重连后,从服务器将从新执行一遍初次复制的过程,发送SYNC命令给主服务器,主服务器执行BGSAVE命令生成RDB文件,同时将在此期间新执行的写命令加入缓冲区,当RDB文件生成完毕,将文件发送给从服务器,而后将缓冲区中新增的命令发送给从服务器,自此主从同步完成。
SYNC命令:一个非常耗资源的操作
1)主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU、内存和磁盘I/O资源。
2)主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应请求命令的时间产生影响。
3)接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求。
所以Redis有必要保证在真正有需要时才执行SYNC命令。
新版复制功能
为了解决旧版本复制功能在处理断线重复制情况时的低效问题,Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操作。
PSYNC命令具有完整完整重同步(full resychronization)和部分重同步(partial resychronization)两种模式:
1)完整重同步:用于处理初次复制情况:完整重同步执行步骤和SYNC命令的执行步骤基本一致。都是通过让主服务器执行BGSAVE命令生成RDB文件,并发送,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。
2)部分重同步:用于处理断线重连后同步复制:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接受并执行这些命令,就可以将数据库更新至主服务器当前所处的状态。
网友评论