复制
用户通过SLAVEOF host port
或者slaveof选项,让一个服务器去复制另一个服务器,被复制的服务器即主服务器,对主服务器进行复制的为从服务器。
数据库状态一致:复制中的主从服务器都保存相同的数据。
旧版复制功能的实现(Redis2.8以前)
复制功能分为同步和命令传播
-
同步:同步用于将从服务器的数据库状态更新至主服务器所处的数据库状态。通过向主服务器发送*
SYNC命令
*来完成。 -
同步的步骤:
* 从服务器向主服务器发送SYNC命令。
* 主服务器收到SYNC命令后执行BGSAVE命令,在后台生成一个RDB文件,并使用缓冲区记录从现在开始执行的所有写命令。
* 当执行完BGSAVE后,主服务器将RDB文件发送给从服务器,从服务器接受后将自己的数据库状态更新至执行BGSAVE命令时的状态。
* 主服务器将记录在缓冲区中的写命令发送给从服务器,让从服务器更新状态至主服务器当前所处的状态。
-
命令传播:主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致,主服务器向从服务器传播相同的写命令,使主从服务器恢复数据一致状态。
-
从服务器对主服务器的复制的两种情况:
1. 初次复制:从服务器以前没有复制过任何主服务器,或者当前要复制的主服务器和上一次复制的主服务器不同。
2. 断线后重复制:在命令传播阶段的主从服务器因为网络问题中断,从服务器通过自动连接重新连上主服务器,并继续复制主服务器。
在旧版中,如果断线了,必须重新向从服务器发送包含全部键的RDB文件,这其中有一部分键的数据是不必要的。
新版复制功能
新版的复制功能解决了旧版的处理断线重复制情况时低效的问题。使用PSYNC命令
代替SYNC命令。PSYNC命令的模式:完整重同步和部分重同步。其中完全重同步用于处理初次复制的情况,处理的步骤和SYNC命令一样。而部分重同步用于处理断线后重复制情况,只需要将从服务器缺少的写命令发送即可。
部分重同步功能由主从服务器复制偏移量、主服务器复制积压缓冲区、服务器的运行ID。
-
复制偏移量:主服务器每次向从服务器传播N个字节数据,在自己的复制偏移量得到值上加N,从服务器每次收到主服务器传播来的N个字节,在自己的复制偏移量是上加N。通过这种机制,能够很简单的判断二者是不是处于一致状态。
-
复制积压缓冲区:主服务器维护的一个固定长度的先进先出的队列,主服务器在命令传播时会把命令写入复制积压缓冲区。
当从服务器重新连接上主服务器,从服务器发送PSYNC命令和自己的复制偏移量给主服务器,1. 如果offset偏移量之后的数据仍然存在复制积压缓冲区,就进行部分重同步。2. 如果不存在了就进行完整重同步。 -
服务器运行ID:初次复制时,从服务器会保存主服务器的ID,在断线重连后,从服务器向主服务器发送保存的ID,如果运行ID和主服务器相同,尝试部分重同步。如果ID不相同,就进行完整重同步。
-
复制的实现步骤
- 从服务器通过【slaveof host Port】 设置主服务器的地址和端口,主服务器返回OK
- 根据IP地址和Port端口,向主服务器创建套接字连接。连接成功就可以发送命令请求和返回命令回复。
- 从服务器发送Ping命令,来检查套接字的读写是否正常和主服务器是否能正常处理命令请求。
- 从服务器收到主服务器返回的Pong回复后,向主服务器发送AUTH命令进行身份验证。
- 身份验证之后,从服务器向主服务器发送从服务器的监听端口号。主服务器收到后就记录下这个状态。
- 从服务器向主服务器发送PSYNC命令,进行完整重同步或者部分重同步。
- 主服务器就可以向从服务器进行命令传播,保持主从服务器一致。
【补充】:在进行完PSYNC同步后,主服务器也成为了从服务器的客户端,这也是主服务器能向从服务器进行命令传播的基础。
- 心跳检测:在命令传播阶段,从服务器默认每秒一次的频率向主服务器发送命令。
- 心跳检测的目的作用:
* 检测主从服务器的网络连接
* 辅助实现min-slave选项
* 检测命令丢失。 - 检测主从服务器的网络连接:如果主服务器超过一秒钟没有收到从服务器发来的ACK命令,就代表二者之间的连接出现了问题。
- 辅助实现min-slave选项:
- 检测命令丢失:如果命令丢失,主服务器将发现从服务器的复制偏移量少于自己,那么就会根据从服务器提交的复制偏移量,在复制积压缓冲区中找到缺少的数据,重新发送。