Redis 复制

Redis 中可以通过执行 SLAVEOF 命令或设置 slaveof 选项,让一个服务器去复制另外一个服务器。

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

同步操作用于将从库数据状态更新至主库数据库状态。

命令传播操作用于 主库被修改时,让主从数据库状态保持一致。

同步

1.从库向主库发送 SYNC命令。

2.受到SYNC命令的主库执行 BGSAVE命令,后台生成一个 RDB文件,并使用缓冲区记录从现在开始执行的所有写命令。

3.主库 BGSAVE 命令执行完毕时,从库会将RDB文件发送给从库,从库载入 RDB文件,将自己的数据库状态更新至主库执行BGSAVE命令时的状态。

4.主库将记录在缓冲区里面所有写命令发送给从库,从库执行这些命令,将自己的数据库状态更新至主库当前所处的状态。

SYNC命令是一个非常消耗资源的操作。无论是生成RDB文件所消耗的内存,I/O,还是将RDB文件发送给从库所占用的网络资源,都会对主从库产生较大的影响(从库载入RDB文件时是阻塞的,无法处理命令请求)。

PSYNC 命令代替SYNC命令来执行复制的同步操作。PSYNC命令分为两部分:

完整同步:与SYNC命令执行步骤一样。

部分同步:专用于处理断线后复制。当从服务器断线后重新连接主服务器,如果条件允许,主服务器可以将从服务器断线期间所执行的写命令发送给从服务器,从服务器接受这些命令并执行就可以更新至主服务器当前状态。

部分同步三部分:

复制偏移量

主服务器和从服务器都会存有一个复制偏移量。当主服务器向从服务器发送字节数据或从服务器接收到主服务器的字节数据时,就会改写这个偏移量。

gQ6UXR.pnggQ6DAK.png

如上图

主库和从库最开始维护的复制偏移位为1000,当主库向从库传输字节数据时,无论是主库还是从库,都会去改写复制偏移位,将1000 + 20字节,改写为1020。

gQ6gcd.png

如果从服务器处于断线状态,则无法维护复制偏移位。通过复制偏移量可以很容易就知道主从库数据状态是否保持一致。

主服务的复制积压缓冲区

复制积压缓冲区是由主服务器维护的一个固定长度先进先出的队列,默认大小为1MB。

当主库进行命令传播时,它不仅会将写命令发送给所有从库,还会将写命令入队到复制积压缓冲区里面。

gQcQvd.png

当断线的服务器A重新连接主服务器时候,它会主动报告自己的复制偏移位 1020,主服务器会立马查询偏移位1020之后的数据是否存在复制积压缓冲区中,如果存在则以部分重同步模式进行后续操作,如果不存在则以完整重同步操作。

复制积压缓冲区的最小大小可根据公式 second * write_size_per_second 来进行估算,即:

2 * 从服务器断线后重新连接主服务器所需的平均时间 * 主服务器平均每秒产生的写命令数据量。

服务器的运行ID

每个服务器都拥有一个运行ID,这个ID在服务启动时自动生成,由40个随机的十六进制字符组成。

当从库对主库初次复制时,主库会将自己的运行ID发送给从库,从库会保存这个ID。当从库断线后重新连接时,从库会向当前连接的主库发送保存的ID。

如果当前连接的主库ID与保存的ID相同,说明主库没有发生改变,可以继续尝试执行部分同步操作。

如果当前连接的主库ID与保存的ID不相同,说明主库发生更换,那么直接进行完整重同步操作。

命令传播

主库会将自己执行的写命令,发送给从库执行。这个行为称为命令传播。

学习资料

《Redis 设计与实现》