Redis的复制
Redis 的复制
概述
分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障处理和负载均衡等功能
配置
建立复制
- 在配置文件中加入 slaveof {masterHost} {masterPort} 启动Redis 生效
- 在redis-server启动 命令后加上 --slaveof {masterHost} {masterPort} 生效
- 直接使用命令 slaveof {masterHost} {masterPort}生效
断开复制
slaveof 命令不但可以建立复制,也可以断开复制,执行slaveof no one 来断开复制 断开复制后并不会抛弃原有数据,只是再也无法获取主节点上的数据变化
拓扑
Redis的复制拓扑结构可以支持单层或多层复制关系:一主一层,一主多层,树状主从结构
-
一主一层结构
-
一主多层
-
树状主从结构
原理
复制过程
- 保存主节点信息 ,执行saveof后从节点保存主节点的地址信息后直接返回
- 从节点内部通过每秒运行的定时任务维护复制相关逻辑,当任务发现存在新的主节点之后,会尝试简历网络连接(建立socket套接字)
- 发送ping命令,检测主从之间套接字是否可用,检测主节点当前是否可接受处理命令
- 权限验证,验证密码等一些东西
- 同步数据集,主从复制连接首次正常通过后,主节点会把所有的数据发送给从节点 这部分操作是最耗时的
- 命令持续复制。主节点同步数据给从节点后,会持续吧命令发送给从节点,保证主从数据一致性
数据同步
全量复制 :一般用于初次复制场景,把主节点数据全部一次发送给从节点,会对主从节点网络造成很大的开销
部分复制 :用于处理在从主之间网络闪断,数据丢失的场景
- 复制偏移量。参与复制的主节点会维护自身偏移量,主节点在处理完写入命令之后,会把命令的字节长度做累加记录,从节点每秒上报自身的复制偏移量给主节点
- 复制积压缓冲区。复制挤压缓冲区是保存在主节点上的宇哥固定长度的队列,当主节点有连接的从节点时被创建,从节点相应写命令时,不但会把命令发送给从节点,也会写入复制积压缓冲区,用于部分复制和复制命令丢失的数据补救
- 主节点运行ID。每个Redis节点启动后都会动态分配一个40位的十六进制字符串作为运行ID。运行ID的主要作用是用来唯一识别的Redis节点
- psync命令。从节点使用psync 命令完成部分复制和全复制功能
全量复制
流程图:
- 发送psync 命令进行数据同步,第一次复制从节点没有复制偏移量和主节点运行ID 所以发送 psync?-1
- 主节点根据1中的命令 解析为全量复制 回复 +FULLRESYNC
- 从节点接受主节点的相应数据保存ID 和 偏移量
- 主节点执行bgsave 保存RDB文件到本地
- 主节点发送RDB文件给从节点
- 从节点接收RDB快照期间,主节点仍然响应读写命令,把命令写入复制客户端缓冲区中,主节点再把缓冲区数据发送给从节点,保证主从数据一致性
- 从节点接受完主节点的全部数据后会清空自身旧数据
- 清空数据后开始加载接收的RDB文件
- 加载完RDB文件后 开启AOF持久化 做bgrewriteaof 操作
部分复制
流程图:
- 当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接.
- 主节点连接中断期间,主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内部存在复制积压缓冲区,依然可保存最近一段时间的数据,默认为1MB.
- 当从节点网络恢复后,从节点会在此连上主节点.
- 当主从连接恢复后,因为之前从节点保存了自身已复制的offset和运行ID,所以会把把其当作psync参数发给主节点.
- 主节点连接到psync命令后,首先核对参数runId是否一致,如果一致说明之前复制的是当前主节点,然后根据offset参数在自身复制积压缓冲区中进行查找,如果偏移量之后的数据存在缓冲区中,则想从节点发送 +CONTINUE 响应,表示进行部分复制.
- 主节点根据偏移量吧复制积压缓冲区里数据发给从节点,以保证主从复制进入正常状态.
心跳
- 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端急性通信,通过 client list 命令查看复制相关客户端信息,主节点的连接状态为 flags = M,从节点的连接状态是 flags = S.
- 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活状态和连接状态,可通过修改配置 repl-ping-slave-period 控制发送频率.
- 从节点在主线程每隔1秒发送 replconf ack{offset} 命令,给主节点上报自身当前的复制偏移量.
- 主节点收到 replconf 信息后,判断从节点超时时间,如果超过 repl-timeout 设置的值(默认值为60 秒),则判断从节点下线,并断开复制客户端连接.
异步复制
主节点不但负责数据读写,还负责把写命令同步给从节点.写命令的发送过程是异步完成的,也就是说主节点自身处理完写命令后直接返回给客户端,并不等待从节点复制完成,如下图所示:
异步复制的流程如下:
- 主节点接受处理命令
- 命令处理完之后返回响应结果
- 对于修改命令异步发送给从节点,从节点在主线程中执行复制的命令.