Redis 的复制功能分为同步(sync)和命令传播(command propagate)两个操作:
本节接下来将对同步和命令传播两个操作进行详细的介绍。
当客户端向从服务器发送 SLAVEOF 命令, 要求从服务器复制主服务器时, 从服务器首先需要执行同步操作, 也即是, 将从服务器的数据库状态更新至主服务器当前所处的数据库状态。
从服务器对主服务器的同步操作需要通过向主服务器发送 SYNC 命令来完成, 以下是 SYNC 命令的执行步骤:
图 IMAGE_SYNC 展示了 SYNC 命令执行期间, 主从服务器的通信过程。
表 TABLE_SYNC_EXAMPLE 展示了一个主从服务器进行同步的例子。
时间 | 主服务器 | 从服务器 |
---|---|---|
T0 | 服务器启动。 | 服务器启动。 |
T1 | 执行 SET k1 v1 。 |
|
T2 | 执行 SET k2 v2 。 |
|
T3 | 执行 SET k3 v3 。 |
|
T4 | 向主服务器发送 SYNC 命令。 | |
T5 | 接收到从服务器发来的 SYNC 命令, 执行 BGSAVE 命令, 创建包含键 k1 、 k2 、 k3 的 RDB 文件, 并使用缓冲区记录接下来执行的所有写命令。 |
|
T6 | 执行 SET k4 v4 , 并将这个命令记录到缓冲区里面。 |
|
T7 | 执行 SET k5 v5 , 并将这个命令记录到缓冲区里面。 |
|
T8 | BGSAVE 命令执行完毕, 向从服务器发送 RDB 文件。 | |
T9 | 接收并载入主服务器发来的 RDB 文件 , 获得 k1 、 k2 、 k3 三个键。 |
|
T10 | 向从服务器发送缓冲区中保存的写命令 SET k4 v4 和 SET k5v5 。 |
|
T11 | 接收并执行主服务器发来的两个 SET 命令, 得到 k4 和 k5 两个键。 |
|
T12 | 同步完成, 现在主从服务器两者的数据库都包含了键 k1 、k2 、 k3 、 k4 和 k5 。 |
同步完成, 现在主从服务器两者的数据库都包含了键 k1 、 k2 、k3 、 k4 和 k5 。 |
在同步操作执行完毕之后, 主从服务器两者的数据库将达到一致状态, 但这种一致并不是一成不变的 —— 每当主服务器执行客户端发送的写命令时, 主服务器的数据库就有可能会被修改, 并导致主从服务器状态不再一致。
举个例子, 假设一个主服务器和一个从服务器刚刚完成同步操作, 它们的数据库都保存了相同的五个键 k1
至 k5
, 如图 IMAGE_CONSISTENT 所示。
如果这时, 客户端向主服务器发送命令 DEL k3
, 那么主服务器在执行完这个 DEL 命令之后, 主从服务器的数据库将出现不一致: 主服务器的数据库已经不再包含键 k3
, 但这个键却仍然包含在从服务器的数据库里面, 如图 IMAGE_INCONSISTENT 所示。
为了让主从服务器再次回到一致状态, 主服务器需要对从服务器执行命令传播操作: 主服务器会将自己执行的写命令 —— 也即是造成主从服务器不一致的那条写命令 —— 发送给从服务器执行, 当从服务器执行了相同的写命令之后, 主从服务器将再次回到一致状态。
在上面的例子中, 主服务器因为执行了命令 DEL k3
而导致主从服务器不一致, 所以主服务器将向从服务器发送相同的命令 DEL k3
: 当从服务器执行完这个命令之后, 主从服务器将再次回到一致状态 —— 现在主从服务器两者的数据库都不再包含键 k3
了, 如图 IMAGE_PROPAGATE_DEL_k3 所示。