你未必出类拔萃,但一定与众不同
Redis 复制
PSYNC命令的实现
PSYNC命令的调用方法共用两种
-
如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one指令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这个时候不可能执行部分重同步)
-
相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC 命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的 复制偏移量,接受到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行那种同步操作
根据情况 接收到PSYNC 命令的主服务器会向从服务器返回以下三种回复的其中一种
-
如果主服务器返回 + FULLRESYNC 回复,那么表示主服务器将与从服务器执行完整重同步操作:其中runid是这个服务器的运行id,从服务器会将 这个id保存下来,在下一次发送psync命令使用,而0ffset则是当前主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量
-
如果主服务器返回+CONTINUE回复,那么表示主服务器将与从服务器执行部分重同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以
-
如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8,它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并且与主服务器执行完整同步操作
复制的实现
复制主要分为以下七步
1.设置主服务器的地址和端口
2.建立套接字
3.发送PING命令
4.身份验证
5.发送端口信息
6.同步
7.命令传播
设置主服务器的地址和端口
当客户端向从服务器发送一下命令时:
slaveof 127.0.0.1 6379
从服务器要做的就是将客户端给定的从服务器的ip地址的127.0.0.1以及端口6379保存到服务器状态的masterhost属性和masterport属性里面。
事实上从服务器将向发送的slaveof命令的客户端返回OK,表示复制指令已经被接受,而实际的复制工作将在OK返回之后才真正开始执行。
建立套接字连接
根据命令设置的ip地址和端口,创建连向主服务器的套接字连接。
发送PING命令
从服务器成为主服务器的客户端之后,做的第一件事情就是发送Ping命令
主要两个作用
- 虽然主从服务器成功建立套接字连接,但是双方还没使用该套接字进行任何通信,通过发送PING命令检查套接字的读写是否正常
- 因为复制工作接下来的几个步骤都必须在主服务器可以正常处理命令请求的状态下才能进行,通过发送PING检查主服务器是否正常接受请求。
发送后可能出现三种情况
- 主服务器返回了一个命令回复,但是从服务器无法读出内容,表示超时,name从服务器断开并且重新连接主服务器
- 主服务器返回一个错误,那么从服务器断开并且重新连接主服务器
- 读取到PONG回复,表示正常
身份验证
从服务器在收到主服务器返回的PONG回复之后,下一步就是身份验证
- 如果从服务器设置了masterauth选项,那么进行身份验证
- 没有设置masterauth选项,不进行身份验证
命令传播
完成同步之后,主服务器就进入命令传播阶段,这时主服务器就会将自己执行的写命令发送给从服务器,而从服务器只要一直接受并且执行从服务器发来的写命令,就可以保证主从服务器一直保持一致了
心跳监测
在命令传播阶段,从服务器会每秒一次的频率,向主服务器发送命令
REPLCONF ACK <replication_offset>
replication_offset是从服务器当前的复制偏移量
发送REPLCONF ACK 命令对于从服务器有三个作用
-
检测主从服务器的网络连接状态
-
辅助实现min—slaves选项
-
监测命令丢失