Redis中可以通过执行slaveof命令或者设置slaveof选项,让一个服务器区复制另一个服务器,被复制的为主服务器,复制的为从服务器。
Redis中可以通过执行slaveof命令或者设置slaveof选项,让一个服务器区复制另一个服务器,被复制的为主服务器,复制的为从服务器
复制功能分为同步和命令传播两个操作
同步操作是将从服务器状态更新为主服务器的数据库状态;
命令传播是主服务器状态被修改时,使主从服务器数据库回归一致状态。
1. 从服务器向主服务器发送SYNC命令。
2.收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,同时在一个缓冲区记录从之后执行的所有写命令。
3.当主服务器的BGSAVE命令执行完毕时,主服务器会将RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
4.主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,使主从服务器状态一致。
简单来说,从服务器向主服务器发送sync命令后,主服务器使用rdb文件记录bgsave执行之前的数据库状态,使用缓冲区保存写命令来记录bgsave执行之后的数据库状态,通过这两种方式来保证主从数据库状态一致。
主服务器将自己执行的写命令发送给从服务器,让两者状态保持一致
旧版的redis断线后重复制需要同步,这是低效的。
从2.8版本开始,断线后重复制使用psync来代替sync。Psync有完全重同步和部分重同步两种模式
完全重同步:初次复制时,让主服务器创建并发送rdb文件,向从服务器发送缓冲区中的写命令
部分重同步:主服务器向从服务器发送断开连接期间的执行的写命令
部分重同步由主服务器和从服务器复制偏移量,主服务器的复制积压缓冲区,服务器的运行id构成
主服务器向从服务器发送n字节数据,复制偏移量加n;从服务器收到n字节数据,复制偏移量加n
主服务器的复制积压缓冲区是固定长度,先进先出的队列,默认为1mb
服务器的运行id启动时自动生成,初次复制,从服务器会保存主服务器id,断线重连后根据id判断是直接执行完整重同步(从服务器保存id与当前主服务器id不同)还是尝试执行部分重同步(id相同)
Psync命令实现
PSYNC命令的调用方法有两种:
1.如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步)。
2.相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNc
根据情况,接收到PSYNC命令的主服务器会向从服务器返回以下三种回复的其中一种:
1.如果主服务器返回+FULLRESYNC
2.如果主服务器返回+CONTINUE回复,那么表示主服务器将与从服务器执行部分重同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了。
3.如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8,它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并与主服务器执行完整同步操作。
主服务器会将自己执行的写命令发送给从服务器。
主服务通过命令传播来更新从服务器状态,从服务器通过向主服务器发送命令来进行心跳检测,命令丢失检测。
在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:
REPLCONF ACK
其中replication_offset是从服务器当前的复制偏移量。
发送REPLCONF ACK命令对于主从服务器有三个作用:
1.检测主从服务器的网络连接状态。
2.辅助实现min-slaves选项。
3.检测命令丢失。
设置主服务器的地址和端口,建立套接字连接,发送ping命令(作用:检查套接字是否正常,检查主服务器是能正常处理命令请求),身份验证,发送端口信息,同步(同步执行前从服务器是主服务器的客户端,同步执行后双方都是对方的客户端),命令传播
总结:主从复制分为同步(全量同步)和命令传播(增量同步)两步操作。reids2.8版本后psync代替了sync,相比于sync是全量同步模式,psync具备了数据全量重同步和部分重同步模式。首先会尝试进行增量同步,不成功则进行全量同步。