Redis主从复制新旧复制功能变化

复制功能

Redis主从复制模式,是将一个redis服务器作为master,其余多个作为slave,从服务器只读不可写,主服务器可读可写,以此来让从服务器分担大部分的只读请求。


主服务器和从服务器之间数据需要同步,这种同步分为两种:历史数据同步和增量数据同步。

历史数据同步

历史数据同步又分为三种:
1.从服务器第一次成为从服务器。
2.从服务器曾经是另外一台主服务器的从服务器。
3.从服务器和主服务器断开,重新连接上。


值得一提的是,Redis的新版复制功能相对于旧版复制功能的优化就主要是为了解决第三种情境——断线重连。

增量数据同步

增量数据同步很好理解,就是在主从服务器正常连接的过程中,客户端向主服务器发送了写命令改变了数据库一致状态,因为主服务器会把该条写命令发送给所有正常连接的从服务器,从服务器执行写命令让数据库状态保持一致。

旧版复制功能

1)从服务器向主服务器发送SYNC命令。
2)收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
3)当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
4)主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。


image.png

旧版复制功能缺陷

这个缺陷主要是断线重连部分,当有从服务器断线重连后,会向主服务器发送SYNC命令(全量同步命令),于是主服务器会根据当前数据库状态生成一个RDB文件发送给从服务器,从服务器载入这个RDB文件。这样操作本身功能是没有什么问题的,只是需要考虑这样一种情况:从服务器和主服务器断开时间很短可能几秒钟就又重新连接上了,这个期间可能主服务器接收到的写命令只有三条,从服务器却要主服务器全量的生成RDB文件来同步,很浪费资源——浪费主服务器的内存资源、IO资源、网络资源,从服务器载入RDB文件过程中也会阻塞掉。

新版复制功能

为了解决旧版复制功能在处理断线重复制情况时的低效问题,Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操作。

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partialresynchronization)两种模式:

❑其中完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。

❑而部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。


image.png

部分同步是如何实现的

关键靠这三个东西:
主服务器的复制偏移量和从服务器的复制偏移量。
主服务器的复制积压缓冲区
服务器的运行ID

复制偏移量——replication offset

主服务器和从服务器都会有一个偏移量,当主服务器向从服务器传播N个字节数据,主服务器就会将自己的偏移量+N,从服务器接收到主服务器传播过来的N个字节,也会将自己的偏移量+N。比如下面:主从服务器的初始偏移量都是100,当主服务器向从服务器传播了N个字节以后,则两边的偏移量都增加了N。
image.png

复制偏移量的作用主要是为主从服务器提供一个可以帮助彼此判断状态是否一致的标识,如果主从服务器的偏移量不一致,则主从状态不一致,这个时候从服务器就要向主服务器发送PSYNC命令了,至于具体是应该完整同步还是部分同步则取决于另外一个因素——复制积压缓冲区。

复制积压缓冲区——replication backlog

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


复制积压缓冲区保留了最近一部分传播的写命令,并且保存的每个字节上都要偏移量,这个队列的大小默认为1M。复制积压缓冲区的主要作用是和偏移量结合起来帮助判断是应该执行完整同步还是部分同步。
image.png
主服务器可以根据从服务器重连后传过来的偏移量来和复制积压缓冲区中的最早偏移量对比,以此来确定从服务器断线这段时间的命令是否都包含在复制积压缓冲区中,如果没有全部包含则进行完整同步,如果全部包含则进行部分同步。

服务器的运行ID——run ID

主从服务器各自都有一个运行ID,以此来确定彼此的身份。

心跳检测

在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset>

心跳检测有三个作用:检测主从服务器的网络连接状态、辅助实现min-slaves选项、检测命令丢失。

检测主从服务器的网络连接状态

这个很好理解,就是相当于一个ping操作,如果主服务器超过1s没有收到来自从服务器的REPLCONF ACK命令,就说明从服务器的连接出现了问题。

辅助实现min-slave选项

这个是依赖于REPLCONF ACK命令来实现的,主服务器会记录每个从服务器最后一次向主服务器发送REPLCONF ACK命令距离现在过去了多少秒,可以在主服务器端通过info replication查看:
image.png
这个lag就是从服务器最后一次向主服务器发送心跳检测命令距离现在过去的秒数,也就代表了从服务器的延迟。于是就可以实现以下的功能:
image.png

检测命令丢失

这个是针对于正常连接的主从服务器,有可能主服务器传播给从服务器的命令会因为网络故障或其他网络问题在传输过程中丢失,这种情况在Redis2.8以前是没有解决方案的,2.8以后有了这个心跳检测功能,每秒从服务器都会向主服务器发送当前自己的偏移量,于是主服务器就可以根据偏移量知道从服务器是否和自己的数据库状态不一致,不一致的话就进行同步,同步过程参考上面断线重连的机制,要么完整同步,要么部分同步。

原文地址:https://www.cnblogs.com/alinainai/p/14061924.html