一、Redis2.8之前的版本,
首先redis复制功能分为同步操作和命令传播两个操作
同步操作作于将从服务器的数据库状态更新至主服务器当前所处的数据库状态
命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的状态不一致时,让主从服务器的数据重回一致状态。
旧版复制实现:
同步:
1,从服务器想主服务器发送SYNC命令
2,收到SYNC命令的主服务器执行BGSAVE命令,然后生成一个RDB文件,并使用一个缓存区记录从现在开始执行命令的所有写命令
3,当主服务器的BGSAVE命令执行完毕,将RDB文件在发送给从服务器,从服务器载入这个RDB文件,在将数据库状态更新至主服务器状态一致
4,主服务器将记录在缓冲区内里的所有写命令发送给从服务器,然从服务器执行这些写命令,将自己的状态更新跟主服务器当前的状态。
命令传播:
当同步操作执行完后,主从服务器状态达到一致,但每当主服务器的数据发生变化时,导致主从服务器的状态不一致。这时 为了主从服务器再次回到一致状态,主服务器需要将自己执行的命令,发送给从服务器执行,这样主从服务器回到一致状态。
旧版复制的缺陷:
断线后重复制:再主从服务器状态一致时,从服务器发生宕机,这时主服务器继续接收客户端发来的写命令,然主服务器这时状态已被修改。从服务器重新连接,从服务器向主服务器发送同步命令,然主服务器执行BGSAVE命令,创建RDB文件,并使用使用缓冲区记录接下来所有的写命令,在发送RDB文件给从服务器,从服务器接收载入这个RDB文件,上诉操作其实从服务器断开连接以前的数据库状态是一致的,不一致的只是从服务器断开后一段时间内的数据,然旧版复制还是将主服务器包含所有数据的RDB文件发送给从服务器,效率极其低下。
Redis2.8之后,新版复制功能实现:
为了解决旧版复制功能在从服务器断线重连后的低效复制问题,从2.8之后,使用PSYNC命令代替SYNC命令来执行复制的同步操作
PSYNC命令具有完整重同步和部分重同步两种模式
其中完整重同步主要用于初次重复制的情况,完整同步实现与SYNC命令步奏一样。
部分重同步则用于处理断线后重复制的情况,它主要实现是在从服务器断线后重连主服务器时,将断线后主服务器接收到的写命令发送给从服务器,从服务器在执行这些命令,从而达到主从服务器状态一致。
部分重同步实现:
1. 复制偏移量
主从服务器各自维护自己的偏移量,主服务器每次向从服务器传播N个字节的数据时,会将自己的复制偏移量加N,然从服务器的复制偏移量的值也加N。如主从服务器的状态一致时,两者的偏移量是相同的。相反如果偏移量不同,说明主从服务器的状态处于不一致状态。
2. 复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度先进先出队列,默认大小为1M,
(可以配置redis.conf文件,write_size_per_second,配置可以根据,从服务器断线时间(S)*平均每秒产生的数据(M))
当主服务器进行命令传播的时候,会将所有写命令发送给从服务器,还会将写命令入队到复制积压缓冲区内,如图:
主服务器的复制积压缓冲区里面会保存着一部分的最近传播的写命令,并且复制积压缓冲区会为队列中的每一个字节记录相应的复制偏移量。
当从服务器重新连上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量决定从服务器执行那种同步操作,
1,如果offset偏移量之后的数据存在于复制积压缓冲区内,那么主服务器将对从服务器执行部分重同步。
2,如果offset偏移量之后的数据不存在于复制积压缓冲区内,那么将执行完整重同步。
问题:如果在从服务器a断线重连后,从服务器a向主服务器发送PSYNC命令,得知从服务器a当前的复制偏移量在999,如果这个时使用部分重复制,则断线期间的数据丢失。
部分重同步实现具体细节:
当从服务器A断线后,立即重新连接主服务器,并向主服务器发送PSYNC命令,并报告自己的复制偏移量为999,
主服务器收到从服务器发送来的PSYNC命令以及偏移量为999之后,主服务器将检查偏移量999以后的数据是否存在于复制积压缓冲区内,如果发现数据亦然存在,则主服务器向从服务器发送+CONTINUE回复,表示数据同步价将以部分重同步模式进行。
接着主服务器会将复制积压缓冲区999偏移量之后的所有数据都发送给从服务器,
从服务器只要接收偏移量999以后的确实数据,就可以回到与主服务器一直状态。
来源:https://www.cnblogs.com/zkdayup/p/11202354.html