Redis在分布式系统中,为了提高可用性,主节点故障可转移到从节点,会把数据复制到多个从节点机器中。
建立主从复制
主节点可以拥有多个从节点,redis为每个启动后的实例动态分配一个40位的十六进制runId,作为唯一识别标志。注意redis重启后,runId会改变。
可以使用debug reload
重新加载RDB并保持runId不变。
在从节点启动时,加上配置参数 slaveof {masterHost} {masterPort}
,可建立与主节点的关系。
通过info replication
命令查看节点当前复制配置内容
断开复制
从节点使用slaveof no one
命令断开与主节点的连接,切换到新主节点会清空当前从节点数据,再进行全量复制。
密码验证
主节点配置requirepass参数进行密码验证,从节点连接时需要配置masterauth参数与主节点密码一致。
只读
从节点一般设置slave-read-only=true
开启只读模式,只复制主节点过来的命令。
传输延迟
主从节点通过网络连接,可能会存在延迟,通过参数repl-disavle-tcp-nodelay
控制TCP_NODELAY,默认为no即开启。
- 当关闭时,主节点的数据会及时发送给从节点,增加带宽消耗,在同一机房中适用
- 当开启时,主节点的数据发送由系统控制,会合并成数据包再发送,发送时间间隔一般是40ms,能节省带宽
主从拓扑结构
一般分为一主一从、一主多从、树形结构(从节点作为中间节点向下传播数据)
复制流程及原理
- slaveof保存主节点内容
- 主从节点建立socket连接
- 从节点发送ping命令检测是否一切正常,主节点返回pong命令回应
- 权限验证,如果配置了密码那就需要验证
- 同步数据集,开始复制(2.8版本后使用psync进行同步)
同步需要了解主从节点命令字节偏移量(offset:节点保存当前复制的位置,通过info replication
查看)、复制积压缓冲区(写命令同时保存到缓冲区队列)、runId(唯一识别节点标志)- 从节点发送psync {runId | ?} {offset}
- 主节点根据runId是否相同返回3种响应
- FULLRESYNC: 全量复制,主节点执行bgsave,保存RDB文件到本地,然后发送给从节点。如果RDB文件从创建到发送完毕耗时超过
repl-timeout(默认60s)
,会导致全量复制失败。
对于从节点开始接受RDB文件到接受完成,主节点响应写命令后会写入复制客户端缓冲区,当从节点加载RDB完成后,再发送缓存区内容。可以通过client=output-buffer-limit 256MB 64MB 60
配置。从节点加载完成后,根据AOF设置可能会发起AOF持久化命令。 - CONTINUE: 部分复制,主节点根据接收的命令中{offset}从复制积压缓冲区查找后续命令补发给从节点。若在repl-backlog-buffer找不到{offset}会升级为全量复制。
- ERR: 无法识别psync命令,从节点将发送sync触发全量复制流程。
- FULLRESYNC: 全量复制,主节点执行bgsave,保存RDB文件到本地,然后发送给从节点。如果RDB文件从创建到发送完毕耗时超过
- 主节点持续发送写命令给从节点保持数据一致
心跳检查
主从连接在建立复制后,维护着长连接并彼此发送心跳命令。
- 通过client list查看节点信息,主节点连接状态flags=M,从节点连接状态flags=S
- 主节点每隔10秒发送ping命令判断从节点的存活性,通过
repl-ping-slave-period
控制 - 从节点每隔1秒发送replconf ack {offset}上报复制偏移量。通过
min-slaves-to-write,min-slaves-max-lag
(lag是主从最后一次通信延迟的秒数)配置
复制需要注意的地方
- 复制数据延迟:宽带延迟和主节点fork阻塞可能会导致数据延迟,从从节点读数据时,最新数据可能不存在
- 读到过期数据:过期键是通过主节点惰性删除、定时删除(快、慢),再发送删除命令给从节点
- 主从配置不一致:如
maxmemory,maxmemory-poricy
或压缩参数不一致时,会导致主从节点数据不一致 - 全量复制:会严重消耗机器资源,需要尽量避免,如第一次建立复制,切换主节点,复制积压缓冲区过小等会导致全量复制。