这是我参与「第五届青训营 」笔记创作活动的第9天
人生没有白走的路,每一步它都算数——考研政治老师孔昱力
1. 主从复制流程
主从复制大体流程可以分为三个阶段:
- 建立连接阶段
- 数据同步阶段
- 命令传播阶段
1.1 建立连接流程
- 为slave设置master的地址和端口,保存master信息
- 设置socket连接
- 发送ping命令(定时器任务)
- 身份验证
- 发送slave端口信息
1.2 数据同步阶段
在slave初次连接master后,复制master中的所有数据到slave。将slave的数据库状态更新成master当前的数据库状态。
首先,slave发送pysnc2指令给master,master收到这个指令后开始执行bgsave,如果是第一个slave连接,还会创建复制缓冲区。然后将bgsave生成的RDB文件通过socket发送给slave。slave接收到RDB文件,首先会保存到外存中,然后将缓存清空,利用RDB进行数据恢复。然后会进入增量复制的命令传播阶段。
数据同步阶段master说明
- 如果master数据量巨大,数据同步阶段应避开流量高峰期,避免造成master阻塞,影响业务正常执行。
- 复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态。
- master单机内存占用主机内存的比例不应过大,建议使用50%-70%的内存,留下30%-50%的内存用于执行bgsave命令和创建复制缓冲区
数据同步阶段slave说明
-
为避免slave进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务
slave-serve-stale-data yes|no -
数据同步阶段,master发送给slave信息可以理解master是slave的一个客户端,主动向slave发送命令
-
slave过多时,建议调整拓扑结构,由一主多从结构变为树状结构,中间的节点既是master,也是slave。注意使用树状结构时,由于层级深度,导致深度越高的slave与最顶层master间数据同步延迟较大,数据一致性变差,应谨慎选择。
1.3 命令传播阶段
当master数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致的状态,同步的动作称为命令传播。master将接收到的数据变更命令发送给slave,slave接收命令后执行命令。
在这个阶段,复制积压缓冲那是非常重要的,所以我么先聊聊它的工作原理。
1.3.1 复制积压缓冲区的工作原理
复制积压缓冲区,简称复制缓冲区,是由偏移量offset和字节值组成。复制缓冲区中存储的是AOF格式的字节值,简单介绍一下AOF的格式
set key value这个命令,以AOF格式会存储为下面这个样子,其中$+数字是代表接下来一行有几个命令字符。
$3\r\n
set\r\n
$3\r\n
key\r\n
$5\r\n
value\r\n
于是复制挤压缓冲区就会存在这样一段
每次命令传播master都会将命令记录下来,并存储在复制缓冲区。复制缓冲区的默认存储空间大小是1M,由于存储空间大小固定,因此最先入队的会被挤出去,让新的元素入队。
master和slave都会保存offset,slave请求同步时会带上自己的offset,然后master会将master offset和slave offset之间的数据发送给slave。
1.3.2 主从服务器复制偏移量
offset就是一个数字,可以理解为指向复制缓冲区中一个字节位置的下标。master会在backlog中保存不同slave的offset。slave只会保存自己的offset。master是每次发送都会记录对应slave的offset,slave是每接收一次记录一次。双方各自保存一份,可以在传输过程中数据丢失时,slave重新索取。
1.4 数据同步 + 命令传播工作流程
当启动一个slave node的时候,它会发送一个PSYNC2命令给master。
首先,slave发送pysnc2指令给master,master收到这个指令后开始执行bgsave,如果是第一个slave连接,还会创建复制缓冲区。然后将bgsave生成的RDB文件通过socket发送给slave,此时会携带该slave对应的offset。slave接收到RDB文件和master的offset、runid。首先会将保存到外存中,然后将缓存清空,利用RDB进行数据恢复。然后会进入增量复制的命令传播阶段。
命令传播阶段slave同样会发送psync2,携带自己的runid和offset。master接收到runid和offset首先会校验这个runid是否是曾经同步过的slave,如果没有通不过就直接全量复制。runid通过后会校验offset是否在缓冲区内,不在缓冲区内说明slave已经很长时间没跟master同步了,自上次同步之后在缓冲区的offset被挤出去了。offset不在缓冲区内就会出发全量复制。如果在缓冲区内,master会将此时master runid和slave runid中间的数据发送给slave。slave接收到AOF文件后,会保存下来,然后执行bgrewriteaof命令,增量恢复数据。
1.5 心跳机制
进入命令传播阶段,master与slave间需要进行信息交换,使用心跳机制进行维护,实现双方连接保持在线
-
master心跳
- 指令:ping
- 周期:由repl-ping-slave-period决定,默认10s
- 作用:判断slave是否在线
- 查询:INFO replication
-
slave心跳
- PERLCONF ACK {offset}
- 周期:1s
- 作用1:汇报slave自己的偏移量,获取最新的数据变更指令
- 作用2:判断master是否在线