x从节点配置上述信息后,启动主节点,然后启动从节点,主节点和从节点就会连接起来,主节点和从节点开始同步操作。
现在,让我们看看这个主从同步流程具体是如何执行的呢以及下面。
首先,让我们来看看整个流程图。 接下来,我将逐步介绍我做了什么。
步骤1 )当主从节点建立连接、协商数据同步和主从节点首次建立连接以进行完全复制时,连接全量复制,即主节点的所有数据在上图的第一步中,是否要从节点发送psync? -1指示并复制主节点。 3358 www.Sina.com/http://www.Sina.com/:每个Redis节点在启动时生成唯一的随机id来标识此Redis节点。 第一次从库中向主库发出复制请求时,不知道主库的runId,是否要将runId设置为问号?其中?代表主节点的 runId;-1 代表复制进度 offset。:如果复制进度为-1,则表示这是第一次复制。 主节点接收到从节点的psync命令时,用FULLRESYNC命令进行响应,并将自身的runId和当前复制进度offset发送到从节点。 步骤2 :在主节点通过RDB文件将所有数据发送到从节点的步骤2中,主节点运行bgsave命令生成RDB文件并将RDB文件发送到从节点。 从节点收到RDB文件后,首先清空自己的数据(防止主从数据不匹配),完成RDB文件的数据加载。 当主节点将数据同步到从节点时,RDB文件由子进程生成,而主节点不被阻止(fork子进程被阻止)。 在此期间,主节点仍会成功接收请求,但这些请求的写入操作未记录在刚生成的RDB文件runId或3358www.Sina.com/中。 步骤3 :主节点向从节点发送在执行步骤2时接收的写入请求,从节点然后重新执行这些操作以实现主从同步。 至此,Redis主从同步的具体执行过程,我们已经很清楚了。offset:在主从复制过程中,Redis在fork子进程中生成RDB文件,该fork子进程的操作阻止了Redis的主线程。 如果从节点非常多,则主节点会被fork子进程追赶,主节点会被阻止,该怎么办? 然后往下看:
此时,可以使用“主-从”模式将主节点生成和发送RDB文件的压力级联到从节点。
简而言之,可以选择配置相对较高的从节点作为其他从节点的主节点,如下图所示。
可以看到,从节点2和从节点3的主节点设置为从节点1,而不是主节点。 这样,可以有效地缓解主节点很多从复制的压力。
那么,除了上述问题以外还有其他问题吗? 答案是肯定的。为了保证主从数据一致性,主节点会把 RDB 文件生成后的写操作记录到内存中的一块缓冲区但是,如果这个连接中断了会怎么样呢?
在Redis2.8之前,replication buffer,这是因为在主从节点断开重新连接后执行总量复制,显然总量复制开销太大
is2.8之后就被淘汰了,升级成了增量复制。那么,什么是增量复制呢? 增量复制断连重连之后,从节点不会复制所有的主节点数据,只会复制断连之后这段时间的写操作数据,这就是增量复制,顾名思义,就是只复制断连后增加的那部分数据量。
增量复制的实现依赖于一个环形缓冲区 repl_backlog_buffer,只要有从节点在,这个环形缓冲区就会存在。主节点会在这个环形缓冲区记录自己写到的位置,从节点会在这个环形缓冲区记录自己已经读到的位置。如下图所示:
主节点的所有写操作除了复制给从节点之外,也会在这个环形缓冲区记录一份,也就是上面说到的主节点会在这个环形缓冲区记录自己写到的位置,只有预先缓存了这些写操作,当从节点断连之后,又恢复连接然后发送 psync {runId} {offset} 命令执行主从同步。主节点才能通过 {offset} 参数在环形缓存区 repl_backlog_buffer 中找到从节点断连的位置,然后发送增量数据(offset位置到主节点写到的位置之间的数据)给从节点。
注意:假如从节点断连时的读位置 offset 已经被主节点的写位置覆盖了,那么此时便无法执行增量复制操作了,只能再执行一次全量复制了。所以,为了尽量避免断连之后的全量复制,可通过 repl_backlog_size 这个参数合理设置 repl_backlog_buffer 的大小,减少发生全量复制的概率。
计算公式:缓冲空间大小 = 主节点写入命令速度 * 操作大小 - 主从节点间网络传输命令速度 * 操作大小
为应对突发情况,可将 repl_backlog_size 设置为缓冲空间大小的2倍。
即:repl_backlog_size = 缓冲空间大小 * 2
接着上面的说,增量数据是如何发送给从节点的呢,这就用到了 replication buffer。
关于 replication buffer 的介绍
Redis和客户端或者从节点通信,都会分配一个对应的内存缓冲,通过这个内存缓冲完成数据交互,如果连接断开,这个内存缓冲也会不复存在。当和从节点进行交互的时候,这个内存缓冲专门用于复制主节点的写操作到从节点,所以叫 replication buffer。如果从节点处理数据特别慢,那么这个replication buffer 会持续增长,可能导致OOM。这个内存缓冲的大小可通过 client-output-buffer-limit 参数限制,如果超过这个限制,主节点会强行断开这个从节点(客户端)的连接。此时复制中断,如果之后再继续发起复制请求,可能会导致恶性循环,引发复制风暴,需格外注意。以上内容参考了极客时间Redis专栏介绍以及yydlz大神的相关说明。
到此,Redis主从复制相关介绍就结束了。
这种模式可以解决Redis的单点故障问题,提高Redis的可用性。但是缺点也是很明显的,假如主节点挂了,从节点是无法自动升级成主节点的,这个过程需要人工处理,在此期间,Redis无法对外提供写操作。此时,Redis哨兵模式就该登场了,待更新…
此外,整个Redis的主从节点数据都是一样的,也就是冗余的,会造成一定的资源浪费。此时,Redis集群模式就该登场了,详见Redis集群搭建