分布式系统中,为了解决单点问题,通常会把数据复制部署到其他机器上,满足故障恢复和负载均衡等需求。

1. 配置

1.1 建立复制

(1)一个主节点可以有多个从节点。在从节点的配置文件中加入slaveof masterhost masterport。
(2)slaveof 指令是异步命令,执行slaveof,节点只保存主节点信息,后续复制流程是在节点内异步执行的。

1.2 断开复制

(1)slaveof no one断开与主节点复制关系。
(2)断开与主节点的复制关系,从节点晋升为主节点。

1.3 切换主节点

(1)使用slaveof 指令
(2)断开与旧主节点复制关系;与新主节点建立复制关系;删除从节点当前的数据;对新的主节点进行复制操作。

1.4 只读

默认从节点配置slave-read-only=true, 只读模式。

2. 拓扑

2.1 一主一从结构

2.2 一主多从结构

2.3 树状结构

3. 原理

3.1 复制过程

(1)保存主节点的信息
(2)主从建立socket连接。如果无法建立连接,从节点会无限尝试。
(3)发送ping命令。 如果没收到pong命令,会断开连接。
(4)权限验证
(5)同步数据集。首次建立复制场景,主节点会把持有数据全部发送给从节点。
(6)命令持续复制。主节点会持续吧写命令发送给从节点,保证主从数据一致性。

3.2 数据同步

(1)使用psync命令完成主从数据同步。
(2)全量复制:一般是初次复制场景。
(3)部分复制:用于主从复制因为网络闪断造成数据丢失的场景。
(4)主从节点自身维护自身的复制偏移量(写命令的字节长度做累加)。

3.3 全量复制

全量复制流程如下:
(1)从节点发送发送psync?-1给主节点。
(2)主节点回复 +FULLRESYNC +runId + offset。
(3)从节点接受到主节点的响应数据,保存运行ID和偏移量offset。
(4)主节点执行bgsave 保存RDB 文件到本地。
(5)主节点发送RDB文件给从节点。
(6)主节点把缓冲区的数据发送给从节点。
(7)从节点清空自身旧的数据。
(8)从节点加载RDB文件。

3.4 部分复制

部分复制流程如下:
(1)当主从节点直接网络出现中断时,如果超过repl-timeout 时间,主节点会认为从节点故障并中断连接
(2)当主从节点网络恢复后,从节点再次连接上主节点。
(3)当主从连接恢复后,由于从节点保存了已复制的偏移量和主节点运行的Id,从节点会通过psync命令把这两个参数发给主节点,进行部分复制。
(4)主节点收到psync命令后,首先核对参数runId 是否和自身一致,把 从节点**+CONTINUE**响应。
(5)然后主节点根据从节点之前发送过来的偏移量把数据发送给从节点。

4. 开发和运维中的问题

4.1 读写分离

对于读占比较高的场景,可以通过把一部分读流量分摊到从节点(slave)赖减轻主节点(master)的压力。可能会遇到下面问题:
(1)数据延迟
通过外部监控程序监听主从节点的复制偏移量。或者采用Redis 集群做水平扩展。
(2)读到过期数据。
(3)从节点故障。
建议:在做读写分离前,可以考虑使用Redis Cluster 等分布式解决方案,这样不止扩展了读性能,还可以扩展写性能和,一致性和故障转移可以得到保证,维护逻辑也容易。

4.2 规避全量复制

会发生全量复制的场景:
(1)第一次建立复制。
(2)主从节点运行ID不匹配。
(3)复制积压缓冲区不足。