数据同步
Redis在2.8及以上版本使用psync命令完成主从数据同步, 同步过程分为: 全量复制和部分复制。
· 全量复制: 一般用于初次复制场景, Redis早期支持的复制功能只有全量复制, 它会把主节点全部数据一次性发送给从节点, 当数据量较大时, 会对主从节点和网络造成很大的开销。
· 部分复制: 用于处理在主从复制中因网络闪断等原因造成的数据丢失场景, 当从节点再次连上主节点后, 如果条件允许, 主节点会补发丢失数据给从节点。 因为补发的数据远远小于全量数据, 可以有效避免全量复制的过高开销。部分复制是对老版复制的重大优化, 有效避免了不必要的全量复制操作。 因此当使用复制功能时, 尽量采用2.8以上版本的Redis。
psync命令运行需要以下组件支持:
·主从节点各自复制偏移量。
·主节点复制积压缓冲区。
·主节点运行id。
复制偏移量
参与复制的主从节点都会维护自身复制偏移量。 主节点(master) 在处理完写入命令后, 会把命令的字节长度做累加记录, 统计信息在info relication中的master_repl_offset指标中:(主节点查看)
从节点(slave) 每秒钟上报自身的复制偏移量给主节点, 因此主节点也会保存从节点的复制偏移量, 统计指标如下:(主节点查看)
从节点在接收到主节点发送的命令后, 也会累加记录自身的偏移量。 统计信息在info relication中的slave_repl_offset指标中:(从节点查看)
复制偏移量的维护如图所示。通过对比主从节点的复制偏移量, 可以判断主从节点数据是否一致。
运维提示:
可以通过主节点的统计信息, 计算出master_repl_offset - slave_offset字节量, 判断主从节点复制相差的数据量, 根据这个差值判定当前复制的健康度。 如果主从之间复制偏移量相差较大, 则可能是网络延迟或命令阻塞等原因引起。
复制积压缓冲区
复制积压缓冲区是保存在主节点上的一个固定长度的队列, 默认大小为1MB, 当主节点有连接的从节点(slave) 时被创建, 这时主节点(master)响应写命令时, 不但会把命令发送给从节点, 还会写入复制积压缓冲区, 如图所示:
由于缓冲区本质上是先进先出的定长队列, 所以能实现保存最近已复制数据的功能, 用于部分复制和复制命令丢失的数据补救。 复制缓冲区相关统计信息保存在主节点的info replication中:
根据统计指标, 可算出复制积压缓冲区内的可用偏移量范围:
[repl_backlog_first_byte_offset,repl_backlog_first_byte_offset+repl_backlog_histlen]。
主节点运行ID
每个Redis节点启动后都会动态分配一个40位的十六进制字符串作为运行ID。 运行ID的主要作用是用来唯一识别Redis节点, 比如从节点保存主节点的运行ID识别自己正在复制的是哪个主节点。 如果只使用ip+port的方式识别主节点, 那么主节点重启变更了整体数据集(如替换RDB/AOF文件),从节点再基于偏移量复制数据将是不安全的, 因此当运行ID变化后从节点将做全量复制。 可以运行info server命令查看当前节点的运行ID:
需要注意的是Redis关闭再启动后, 运行ID会随之改变, 例如执行如下命令:
如何在不改变运行ID的情况下重启呢?当需要调优一些内存相关配置, 例如: hash-max-ziplist-value等, 这些配置需要Redis重新加载才能优化已存在的数据, 这时可以使用debug reload命令重新加载RDB并保持运行ID不变, 从而有效避免不必要的全量复制。 命令如下:
运维提示:
debug reload命令会阻塞当前Redis节点主线程, 阻塞期间会生成本地RDB快照并清空数据之后再加载RDB文件。 因此对于大数据量的主节点和无法容忍阻塞的应用场景, 谨慎使用。
psync命令
从节点使用psync命令完成部分复制和全量复制功能, 命令格式:psync{runId}{offset}, 参数含义如下:
·runId: 从节点所复制主节点的运行id。
·offset: 当前从节点已复制的数据偏移量。
流程说明:
1) 从节点(slave) 发送psync命令给主节点, 参数runId是当前从节点保存的主节点运行ID, 如果没有则默认值为?, 参数offset是当前从节点保存的复制偏移量, 如果是第一次参与复制则默认值为-1。
2) 主节点(master) 根据psync参数和自身数据情况决定响应结果:
·如果回复+FULLRESYNC{runId}{offset}, 那么从节点将触发全量复制流程。
·如果回复+CONTINUE, 从节点将触发部分复制流程。
·如果回复+ERR, 说明主节点版本低于Redis2.8, 无法识别psync命令,从节点将发送旧版的sync命令触发全量复制流程。
对应的日志如下: