一文深入Redis主从复制的原理详解

复制原理
【一文深入Redis主从复制的原理详解】1.复制过程
复制的过程步骤如下:
1、从节点执行slaveof命令
2、从节点只是保存了slaveof命令中主节点的信息,并没有立即发起复制
3、从节点内部的定时任务发现有主节点的信息,开始使用socket连接主节点
4、连接建立成功后,发送ping命令,希望得到pong命令响应,否则会进行重连
5、如果主节点设置了权限,那么就需要进行权限验证;如果验证失败,复制终止 。
6、权限验证通过后,进行数据同步,这是耗时最长的操作,主节点将把所有的数据全部发送给从节点 。
7、当主节点把当前的数据同步给从节点后,便完成了复制的建立流程 。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性 。
2.数据间的同步
上面说的复制过程,其中有一个步骤是“同步数据集”,这个就是现在讲的‘数据间的同步’ 。
redis同步有2个命令:
sync和psync,前者是redis2.8之前的同步命令,后者是redis2.8为了优化sync新设计的命令 。我们会重点关注2.8的psync命令 。
psync命令需要3个组件支持:
1、主从节点各自复制偏移量2、主节点复制积压缓冲区3、主节点运行ID
主从节点各自复制偏移量:
1、参与复制的主从节点都会维护自身的复制偏移量 。2、主节点在处理完写入命令后,会把命令的字节长度做累加记录,统计信息在inforeplication中的masterreploffset指标中 。3、从节点每秒钟上报自身的的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量 。4、从节点在接收到主节点发送的命令后,也会累加自身的偏移量,统计信息在inforeplication中 。5、通过对比主从节点的复制偏移量,可以判断主从节点数据是否一致 。
主节点复制积压缓冲区:
1、复制积压缓冲区是一个保存在主节点的一个固定长度的先进先出的队列 。默认大小1MB 。
2、这个队列在slave连接是创建 。这时主节点响应写命令时,不但会把命令发送给从节点,也会写入复制缓冲区 。
3、他的作用就是用于部分复制和复制命令丢失的数据补救 。通过inforeplication可以看到相关信息 。
主节点运行ID:
1、每个redis启动的时候,都会生成一个40位的运行ID 。
2、运行ID的主要作用是用来识别Redis节点 。如果使用ip+port的方式,那么如果主节点重启修改了RDB/AOF数据,从节点再基于偏移量进行复制将是不安全的 。所以,当运行id变化后,从节点将进行全量复制 。也就是说,redis重启后,默认从节点会进行全量复制 。
如果在重启时不改变运行ID呢?
1、可以通过debugreload命令重新加载RDB并保持运行ID不变 。从而有效的避免不必要的全量复制 。
2、他的缺点则是:debugreload命令会阻塞当前Redis节点主线程,因此对于大数据量的主节点或者无法容忍阻塞的节点,需要谨慎使用 。一般通过故障转移机制可以解决这个问题 。
psync命令的使用方式:
命令格式为psync{runId}{offset}
runId:从节点所复制主节点的运行idoffset:当前从节点已复制的数据偏移量
psync执行流程:
一文深入Redis主从复制的原理详解
文章插图
流程说明:从节点发送psync命令给主节点,runId就是目标主节点的ID,如果没有默认为-1,offset是从节点保存的复制偏移量,如果是第一次复制则为-1.
主节点会根据runid和offset决定返回结果:
1、如果回复+FULLRESYNC{runId}{offset},那么从节点将触发全量复制流程 。
2、如果回复+CONTINUE,从节点将触发部分复制 。
3、如果回复+ERR,说明主节点不支持2.8的psync命令,将使用sync执行全量复制 。
到这里,数据之间的同步就讲的差不多了,篇幅还是比较长的 。主要是针对psync命令相关之间的介绍 。
3.全量复制
全量复制是Redis最早支持的复制方式,也是主从第一次建立复制时必须经历的的阶段 。触发全量复制的命令是sync和psync 。之前说过,这两个命令的分水岭版本是2.8,redis2.8之前使用sync只能执行全量不同,2.8之后同时支持全量同步和部分同步 。
流程如下:
一文深入Redis主从复制的原理详解
文章插图
介绍一下上图步骤:
1、发送psync命令(spync?-1)
2、主节点根据命令返回FULLRESYNC
3、从节点记录主节点ID和offset
4、主节点bgsave并保存RDB到本地
5、主节点发送RBD文件到从节点
6、从节点收到RDB文件并加载到内存中
7、主节点在从节点接受数据的期间,将新数据保存到“复制客户端缓冲区”,当从节点加载RDB完毕,再发送过去 。(如果从节点花费时间过长,将导致缓冲区溢出,最后全量同步失败)8、从节点清空数据后加载RDB文件,如果RDB文件很大,这一步操作仍然耗时,如果此时客户端访问,将导致数据不一致,可以使用配置slave-server-stale-data关闭.9、从节点成功加载完RBD后,如果开启了AOF,会立刻做bgrewriteaof 。
以上加粗的部分是整个全量同步耗时的地方 。
注意:
1、如过RDB文件大于6GB,并且是千兆网卡,Redis的默认超时机制(60秒),会导致全量复制失败 。可以通过调大repl-timeout参数来解决此问题 。
2、Redis虽然支持无盘复制,即直接通过网络发送给从节点,但功能不是很完善,生产环境慎用 。
4.部分复制
当从节点正在复制主节点时,如果出现网络闪断和其他异常,从节点会让主节点补发丢失的命令数据,主节点只需要将复制缓冲区的数据发送到从节点就能够保证数据的一致性,相比较全量复制,成本小很多 。
步骤如下:
一文深入Redis主从复制的原理详解
文章插图
1、当从节点出现网络中断,超过了repl-timeout时间,主节点就会中断复制连接 。
2、主节点会将请求的数据写入到“复制积压缓冲区”,默认1MB 。
3、当从节点恢复,重新连接上主节点,从节点会将offset和主节点id发送到主节点
4、主节点校验后,如果偏移量的数后的数据在缓冲区中,就发送cuntinue响应——表示可以进行部分复制
5、主节点将缓冲区的数据发送到从节点,保证主从复制进行正常状态 。
5.心跳
主从节点在建立复制后,他们之间维护着长连接并彼此发送心跳命令 。
心跳的关键机制如下:
1、中从都有心跳检测机制,各自模拟成对方的客户端进行通信,通过clientlist命令查看复制相关客户端信息,主节点的连接状态为flags=M,从节点的连接状态是flags=S 。
2、主节点默认每隔10秒对从节点发送ping命令,可修改配置repl-ping-slave-period控制发送频率 。
3、从节点在主线程每隔一秒发送replconfack{offset}命令,给主节点上报自身当前的复制偏移量 。
4、主节点收到replconf信息后,判断从节点超时时间,如果超过repl-timeout60秒,则判断节点下线 。
一文深入Redis主从复制的原理详解
文章插图
注意:为了降低主从延迟,一般把redis主从节点部署在相同的机房/同城机房,避免网络延迟带来的网络分区造成的心跳中断等情况 。
6.异步复制
主节点不但负责数据读写,还负责把写命令同步给从节点,写命令的发送过程是异步完成,也就是说主节点处理完写命令后立即返回客户度,并不等待从节点复制完成 。
异步复制的步骤很简单,如下:
1、主节点接受处理命令2、主节点处理完后返回响应结果3、对于修改命令,异步发送给从节点,从节点在主线程中执行复制的命令 。
一文深入Redis主从复制的原理详解
文章插图
总结
本文主要分析了Redis的复制原理,包括复制过程,数据之间的同步,全量复制的流程,部分复制的流程,心跳设计,异步复制流程 。
其中,可以看出,RDB数据之间的同步非常耗时 。所以,Redis在2.8版本退出了类似增量复制的psync命令,当Redis主从直接发生了网络中断,不会进行全量复制,而是将数据放到缓冲区(默认1MB)里,在通过主从之间各自维护复制offset来判断缓存区的数据是否溢出,如果没有溢出,只需要发送缓冲区数据即可,成本很小,反之,则要进行全量复制,因此,控制缓冲区大小非常的重要 。
责任编辑:lq
.dfma {position: relative;width: 1000px;margin: 0 auto;}.dfma a::after {position: absolute;left: 0;bottom: 0;width: 30px;line-height: 1.4;text-align: center;background-color: rgba(0, 0, 0, .5);color: #fff;font-size: 12px;content: "广告";}.dfma img {display: block;}
一文深入Redis主从复制的原理详解
文章插图

    推荐阅读