Reids复制数据主要有2种场景:
1. 从服务器历来第一次和当前主服务器链接,即初次复制
2. 从服务器断线后从新和以前链接的主服务器恢复链接,即断线后重复制
对于初次复制来讲使用SYNC命令进行全量复制是合适高效的,可是对于断线后重复制来讲效率就不太能接受了。举例来讲:
如图所示,Master在断开链接期间只传播了3个写入命令,可是从新链接以后却要全量复制,显然这是低效而且不太必要的。缓存
为了应对这种状况,Redis在2.8版本提供了PSYNC命令来带代替SYNC命令,为Redis主从复制提供了部分复制的能力。PSYNC命令格式是:服务器
PSYNC <runid> <offset> runid:主服务器ID offset:从服务器最后接收命令的偏移量
PSYNC执行过程当中比较重要的概念有3个:runid、offset(复制偏移量)以及复制积压缓冲区。spa
每一个Redis服务器都会有一个代表本身身份的ID。在PSYNC中发送的这个ID是指以前链接的Master的ID,若是没保存这个ID,PSYNC的命令会使用”PSYNC ? -1” 这种形式发送给Master,表示须要全量复制。code
在主从复制的Master和Slave双方都会各自维持一个offset。Master成功发送N个字节的命令后会将Master的offset加上N,Slave在接收到N个字节命令后一样会将Slave的offset增长N。Master和Slave若是状态是一致的那么它的的offset也应该是一致的。xml
复制积压缓冲区是由Master维护的一个固定长度的FIFO队列,它的做用是缓存已经传播出去的命令。当Master进行命令传播时,不只将命令发送给全部Slave,还会将命令写入到复制积压缓冲区里面。队列
理解了上面三个基本概念,PSYNC的执行过程就好理解了。
1 客户端向服务器发送SLAVEOF命令,让当前服务器成为Slave;
2 当前服务器根据本身是否保存Master runid来判断是不是第一次复制,若是是第一次同步则跳转到3,不然跳转到4;
3 向Master发送PSYNC ? -1 命令来进行完整同步;
4 向Master发送PSYNC runid offset;
5 Master接收到PSYNC 命令后首先判断runid是否和本机的id一致,若是一致则会再次判断offset偏移量和本机的偏移量相差有没有超过复制积压缓冲区大小,若是没有那么就给Slave发送CONTINUE,此时Slave只须要等待Master传回失去链接期间丢失的命令;
6 若是runid和本机id不一致或者双方offset差距超过了复制积压缓冲区大小,那么就会返回FULLRESYNC runid offset,Slave将runid保存起来,并进行完整同步。同步