0%

Redis学习笔记--Redis 主从复制技术原理

理论上的主从复制技术设计

主从复制技术有两个版本,2.8 以前的版本,设计上有缺陷,在 slave 断线后重连依然需要 master 重新发送 RDB 重新进行数据更新,效率非常低。2.8 版本以后做了重新设计,通过引入偏移量同步,相对而言非常的高效,我们这里不去讨论旧版本的设计了,直接看新版本的主从复制技术设计。

每一个 Redis 启动后,都会认为自己是一个 master 节点,你可以通过以下命令通知它成为 slave 并向 master 同步数据:

1
2
slaveof [masterip] [masterport]

另一种方式就是在 Redis 启动配置文件中直接指明让它作为一个 slave 节点启动,并在启动后同步 master 节点数据。配置项和命令是一样的。

如果 master 配置了密码连接,那么还需要在 slave 的配置文件中指明 master 的连接密码:

1
masterauth <password>

除此之外,salve 节点默认是只读的,不允许写入数据,因为如果支持写入数据,那么与 master 就无法保持数据一致性,所以我们一般会把 slave 节点作为读写分离中读服务提供者。当然,你也可以修改是否允许 slave 写入数据:

1
slave-read-only yes/no

当然如果你的 master 宕机了,你需要把某个 slave 上线成 master,你可以通过命令取消 slave 的数据同步,成为单独的一个 master:

1
slaveof no one

slave 同步 master 的数据主要分为两个大步骤,全量复制和部分复制。当我们执行 slaveof 命令的时候,我们的 slave 会作为一个客户端连接上 master 并向 master 发送 PSYNC 命令。

master 收到命令后,会调用 bgsave fork 一个后台子进程生产 RDB 文件,待合适的时候,在 serverCron 循环的时候发送给 slave节点。

slave 收到 RDB 文件后,丢弃目前内存中所有的数据并阻塞自己,专心做 RDB 读取,数据恢复。

以上就是主从复制的一个全量复制的大概流程,但是一次全量复制并不能永远的保持主从节点数据一致,master 还需要将实时的修改命令同步到从节点才行,这就是部分复制。

在介绍部分复制之前,这里先介绍几个概念。第一个是复制缓冲区(repl_backlog),这是一个 FIFO 的队列,里面存的是最近的一些写命令,大小默认在 1M,复制偏移量(offset),这个偏移量其实是对应复制缓冲区中的字符偏移。复制缓冲区的结构大致是这样的:

在主从节点完成第一轮全量复制以后,主从节点之间已经初步实现了数据同步,往后的 master,会将收到的每一条写命令发送给 slave 并 添加到复制缓冲区并根据字节数计算更新自己的偏移量,slave 收到传输过来的命令后也一样更新自己的偏移量。

这样,只要主从节点的偏移量相同就说明主从节点之间的数据是同步的。复制缓冲区大小是固定的,新的写命令进来以后,旧的数据就会出队列。如果某个 slave 断线重连之后,依然向 master 发送 PSYNC 命令并携带自己的偏移量,master 判断该偏移量是否还在缓冲区区间内,如果在则直接将该偏移量往后的所有偏移量对应的命令发送给 slave,无需重新进行全量复制。

这是新版同步复制的一个优化的设计,如果该断线重连的 slave 的偏移量已经不在缓冲区区间内,那么说明 master 可能已经无法找到自上次断线后的完整更新记录了,于是进行全量复制并将最新的偏移量发到 slave,算是完成了新的数据同步。