第七章 复制
用户可以通过SLAVEOF命令让一个服务器去复制另一个服务器,下面命令中,127.0.0.1:12345是从服务器,127.0.0.1 6379是主服务器。

1. 旧版复制功能的实现
Redis的复制功能分为同步(sync)和命令传播(command propagate)两个操作:
- 同步操作用于将从服务器的数据库状态更新至主服务器当前所处状态
- 命令传播操作用于在主服务器的数据库状态被修改后,让主从服务器的数据库重新回到一致状态
1.1 同步

1.2 命令传播
当完成同步操作后,主服务器会将之后执行的写命令发送给从服务器执行,以使主从服务器保持一致。
2 旧版复制功能的缺陷
从服务器对主服务器的复制一般分为两种情况:
- 初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同
- 断线后重复制:处于命令传播阶段的主从服务器因为网络问题而中断了复制,但从服务器通过自动重连接连上了主服务器,并继续复制主服务器
旧版复制功能断线后重复制效率很低,如表15-2例子所示:

主从服务器在T0到T10086一直处于一致状态,真正需要主服务器添加的K10087, K10088, K10089三个键的数据。但是,实际上主服务器生成并向从服务器发送包含键K1至K10089的RDB文件。而SYNC命令是一个非常耗费资源的操作。
3 新版复制功能的实现
PSYNC命令包含完整重同步和部分重同步两种模式:
- 完整重同步的执行步骤与SYNC命令基本一致
- 部分重同步只将主从服务器断开期间执行的写命令发送给从服务器

4. 部分重同步的实现
部分重同步由以下三部分构成:
- 主服务器的复制偏移量和从服务器的复制偏移量
- 主服务器的复制积压缓冲区
- 服务器的运行ID
4.1 复制偏移量
主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N。从服务器每次收到主服务器传播来的N字节数据时,就将自己的复制偏移量的值加N。

4.2 复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队列(后进入的数据会将最先进入队列的数据踢出队列),默认大小为1MB.

当从服务器重新连接主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器:
- 如果offset偏移量之后的数据,仍然存在于复制积压缓冲区里,主服务器对从服务器执行部分重同步操作
- 如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作
4.3 服务器运行ID
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID(40个随机16进制字符组成)传送给从服务器,在网络断开后,从服务器重新连接上主服务器后,从服务器将向主服务器发送这个ID,主服务器确定是否是自己的ID,是则执行部分重同步,否则执行完整重同步。
5 PSYNC命令的实现
6. 心跳检测
在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:
REPLCONF ACK <replication_offset>
其中replication_offset是从服务器当前的复制偏移量
发送REPLCONF ACK命令主要有三个作用:
- 检测主从服务器的网络连接状态
- 辅助实现min-slaves选项 Redis的min-slaves-to-write和min-slaves-max-lag两个选项可以防止主服务器在不安全的情况下执行写命令
- 检测命令丢失 比较主服务器和从服务器的复制偏移量

浙公网安备 33010602011771号