1 旧版复制功能的实现

Redis复制功能分为同步和命令传播两个操作:

1)       同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态

2)       命令传播则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致的状态。

2 新版复制功能的实现

为了解决旧版复制功能在处理断线重复制情况时的低效问题,新版Redis使用PSYNC命令代替SYNC命令来执行复制时的同步操作。

PSYNC命令有完整重同步和部分重同步两种模式:

1)       其中完整重同步用于处理初次复制的情况,完整重同步的执行步骤和旧版的SYNC执行步骤一样,都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。

2)       而部分重同步则用于断线后重复制的情况:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器。从服务器只要接受并执行这些命令,就可以将数据库更新至主服务器所处的状态。

3 部分重同步的实现

部分重同步由以下三个部分构成:

1)       主服务器的复制偏移量和从服务器的复制偏移量

2)       主服务器的复制积压缓冲区(命令传播时,主服务器不仅将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区)

3)       服务区的运行ID

当从服务器重新连上主服务器时,从服务器会通过 PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定从服务器执行何种同步操作:

1)       如果offset偏移量之后的数据仍然存在于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作。

2)       如果offset偏移量之后的数据已经不存在与复制积压缓冲区,那么主服务器将对服务器执行完整的重同步的操作。

当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,而从服务器则将这个运行ID保存起来,当从服务器断线后重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:

1)       如果从服务器保存的运行ID和当前连接的主服务器的运行ID相同,那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可继续尝试执行部分同步操作。

2)       如果从服务器保存的运行ID和当前连接的主服务器运行ID并不相同。那么主服务器将对从服务器执行完整同步操作。

4 复制的实现

1)       设置主服务器的地址和端口

2)       建立套接字连接

3)       发送PING命令

4)       身份验证

5)       发送端口信息

6)       同步

7)       命令传播

5 心跳检测

在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令REPLCONFACK <replication_offset>,其中replication_offset是从服务器当前的复制偏移量。

发送REPLCONF ACK命令对于主从服务器有三个作用:

1)       检测主从服务器的网络连接状态

2)       辅助实现min-slaves选项

3)       检测命令丢失