26 redis 中 replication/cluster 集群中的主从复制
前言
我们这里首先来看?redis?这边实现比较复杂的?replication集群模式?
我们这里主要关注的是 redis?这边的主从同步的相关实现
这边相对比较简单,?我们直接基于?cluster集群模式 进行调试
?
?
主从命令同步复制
比如这里 master 是?redis_7002, slave 是?redis_7005
然后?这里是 master?这边直接同步?相关命令到各个 slave?
?
然后这里是在 server.call:3765 进行命令存储到?backlog, aof, 以及同步发送到?slave?
命令真实执行是在?server.call:3675 的?cmd->proc->proc(c)
?
然后?redis_7005 这边拿到命令之后,?开始执行, 这个执行过程就和客户端这边发送执行命令一样?
?
?
全量同步
整个流程分为两个 part, 一个是请求方,?就是?slave, 一个是提供方,?是?master?
slave 这边连接到?master?之后,?slave 发送?SYNC?命令到?master?
master 通知客户端需要全量同步, 然后?master?这边后台去?dump?内存快照文件
slave 这边等待?master?这边?dump?内存快照文件,?并通过网络传递过来?
master 这边?dump?内存快照文件生成之后,?会向?slave?这边进行传输
slave 这边拿到?master?的?dump?的内存快照信息,?将其持久化到 临时文件,?完成之后重命名为?dump.rdb, 然后清空当前数据库,?然后?加载 dump.rdb?文件进行一个快照的数据恢复?
我们这里?一边一边的看, 先看?slave, 再看?master?
?
slave 的处理
这个是?slave?这边启动的时候?就会进行的一个操作
这里?syncWithMaster 根据?server.repl_state 这边同步的处理了几个?slave?和?master?的交互,?分为了几个不同的阶段?REPL_STATE_CONNECT, REPL_STATE_CONNECTING, REPL_STATE_RECEIVE_PING_REPLY, REPL_STATE_SEND_HANDSHAKE 等等?
比如这里会?发送 ping?给?master, 然后等待?master?这边回复信息?
在发送?masterauth 等相关信息,?REPLCONF 等相关信息?
?
后面和全量同步相关比较重要的流程就是?发送?SYNC?相关命令?
?
然后?slave?这边会收到?master?这边的?FULLRESYNC?的通知?
?
然后就是后面?slave?这边创建临时文件,?然后准备接受?master?这边?后台持久化 rdb?文件之后传递给?slave?这边,?之后的处理交给?readSyncBulkPayload
?
接受服务器这边传输过来的 rdb?文件的相关信息,?持久化到?上面创建的临时文件 repl_transfer_tmpfile
?
然后就是 清空 slave?本地数据库,?然后重命名?临时文件 为?dump.rdb
然后加载?dump.rdb 到?slave?本地数据库?
?
触发上面?syncWithMaster 的地方,?从上下文是可以看到是?serverCron 注册了一个定时任务,?100ms 跑一次,?跑的任务是?clusterCron 相关,?里面包含了这里的?connectWithMaster
所以节点的上下线?是可以再 100ms 左右感知到的?
?
客户端这边相关日志如下,?基本上是?syncWithMaster + readSyncBulkPayload 这两部分中输出的?
前面两行是 connectWithMaster 中输出的连接?master?的相关日志?
后面的是?slave?这边向?master?发送 PING, master 进行回复?
后面的是?slave?这边发送?SYNC?指令,?询问是否可以增量同步,?master 这边回复?只能全量同步
然后是?slave?这边接收到了?master?的?dump.rdb?的数据信息,?合计210字节,?清空?slave?的数据库,?从?dump.rdb 中加载数据到?slave?的数据库,?最终同步成功?
?
?
master 的处理
需要全量同步的有几个场景?
场景1?是?slave 未传递同步偏移,?或者偏移传递错误?
场景2?是?master 和?slave?两边的?replyid 对不上?
场景3?是?slave 这边传递的偏移不在?master?这边数据同步的偏移区间内, 偏移错误?或者 落后的太多
?
然后就是?master?这边处理全量同步的大头了?
场景1?如果是已经在进行?dump 内存快照文件,?则等待即可?
场景2?如果是已经在?dump?内存快照,?并且通过?tcp 直接传输数据,?则只能等待操作完成?
场景3?master 可以?dump?内存快照,?或者直接通过 tcp?传输数据,?
?
处理如下,?通过?startBgsaveForReplication 进行逻辑上的分发?
是?dump?内存快照文件,?还是?dump内存快照直接通过 tcp?传输数据?
?
然后这里就是?fork?出子进程,?让子进程?来 dump?内存快照,?并保存到目标文件?
?
然后 master?这边有定时任务在定时检查?子进程是否完成, 周期为?1秒?
如果完成了,?则向?slave?这边传输?dump?的内存快照的数据?
?
master 这边日志如下?
slave 这边发送过来了?PSYNC 的请求?
然后?master?这边判断?replyid,?replyid2 匹配不上,?然后开始进行?全量同步?
然后?master?开始进行 dump?内存快照,?fork 子进程?来生成 dump.rdb
master dump 内存快照生成完成之后,?发送数据到?slave, 之后记录?成功日志
?
?
基于?backlog 的增量同步
master 这边添加增量命令到?backlog
命令到 server.call:3765 的时候,?会将命令添加到?backlog 队列?
其中存储的数据就是?具体的执行命令,?存储在了一个数据中, 比如这里的?“set name4 jerry17”, 会将其存储为?一个长度为3的数组,?元素分别为?[“set”, “name4”, “jerry17”]
?
具体的复制命令到 backlog?中的相关处理如下,?可以简单理解为一个?memcpy 进去,?然后更新?索引 repl_backlog_idx
?
?
slave 这边长时间和?master?失联,?重新连接之后发送?PSYNC?增量同步请求
clusterCron 为定时任务,?定时扫描集群的状态,?如果失联了,?则重新建立连接?
同样是在?syncWithMaster 的代码中, 这里传入了?replyid 和?offset?到?master?
?
?
master 这边获取增量的命令响应给客户端
比如这里传输了?134 字节的命令数据到客户端, 我们?再来看一下 详细的命令信息
?
从响应的字符串信息中可以看到,?传输了?“select 0”, “set name4 jerry18”, “set name4 jerry19”, “set name4 jerry20” 四条命令,?其中?“select 0” 是?redis?自己增加的,?然后?其他的几个命令是 客户端这边交互产生的
?
?
slave 这边收到命令之后执行
客户端这边接收到这一批次的命令之后,?依次进行执行?“select 0”, “set name4 jerry18”, “set name4 jerry19”, “set name4 jerry20” 进而实现了增量的同步?
?
?
完
?
?
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!