26 redis 中 replication/cluster 集群中的主从复制

前言

我们这里首先来看 redis 这边实现比较复杂的 replication集群模式 

我们这里主要关注的是 redis 这边的主从同步的相关实现

这边相对比较简单, 我们直接基于 cluster集群模式 进行调试

 

 

主从命令同步复制

比如这里 master 是 redis_7002, slave 是 redis_7005

然后 这里是 master 这边直接同步 相关命令到各个 slave 

a19730e124774c85857090955e267bc1.png

 

然后这里是在 server.call:3765 进行命令存储到 backlog, aof, 以及同步发送到 slave 

命令真实执行是在 server.call:3675 的 cmd->proc->proc(c)

418fbbc6622a45fcbacaabe770ce8a0c.png

 

然后 redis_7005 这边拿到命令之后, 开始执行, 这个执行过程就和客户端这边发送执行命令一样 

e696cfc4a7874538a99cdc3dceaf3285.png

 

 

全量同步

整个流程分为两个 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 等相关信息 

940a1e1b87924188a50abcc903662b87.png

 

后面和全量同步相关比较重要的流程就是 发送 SYNC 相关命令 

4a39f9fed3e045e2b222f3c318044dc3.png

 

然后 slave 这边会收到 master 这边的 FULLRESYNC 的通知 

34b74496b62949cda7472938880967fa.png

 

然后就是后面 slave 这边创建临时文件, 然后准备接受 master 这边 后台持久化 rdb 文件之后传递给 slave 这边, 之后的处理交给 readSyncBulkPayload

13b038ad45434cd3ad20a771daccc517.png

 

接受服务器这边传输过来的 rdb 文件的相关信息, 持久化到 上面创建的临时文件 repl_transfer_tmpfile

b0c87aeb46884d6aab1a5b22d8bcd4ed.png

 

然后就是 清空 slave 本地数据库, 然后重命名 临时文件 为 dump.rdb

然后加载 dump.rdb 到 slave 本地数据库 

2b7f847234874d599af93f8000cfbfdd.png

 

触发上面 syncWithMaster 的地方, 从上下文是可以看到是 serverCron 注册了一个定时任务, 100ms 跑一次, 跑的任务是 clusterCron 相关, 里面包含了这里的 connectWithMaster

所以节点的上下线 是可以再 100ms 左右感知到的 

6ead85e84fc64625b0fdd0679f2f5bc7.png

 

客户端这边相关日志如下, 基本上是 syncWithMaster + readSyncBulkPayload 这两部分中输出的 

前面两行是 connectWithMaster 中输出的连接 master 的相关日志 

后面的是 slave 这边向 master 发送 PING, master 进行回复 

后面的是 slave 这边发送 SYNC 指令, 询问是否可以增量同步, master 这边回复 只能全量同步

然后是 slave 这边接收到了 master 的 dump.rdb 的数据信息, 合计210字节, 清空 slave 的数据库, 从 dump.rdb 中加载数据到 slave 的数据库, 最终同步成功 

e6e4e511e17a4d33b9c4d079075d44da.png

 

 

master 的处理

需要全量同步的有几个场景 

场景1 是 slave 未传递同步偏移, 或者偏移传递错误 

场景2 是 master 和 slave 两边的 replyid 对不上 

场景3 是 slave 这边传递的偏移不在 master 这边数据同步的偏移区间内, 偏移错误 或者 落后的太多

c5c9b8775a3444bd9eec5f6bde5487f7.png

 

然后就是 master 这边处理全量同步的大头了 

场景1 如果是已经在进行 dump 内存快照文件, 则等待即可 

场景2 如果是已经在 dump 内存快照, 并且通过 tcp 直接传输数据, 则只能等待操作完成 

场景3 master 可以 dump 内存快照, 或者直接通过 tcp 传输数据, 

af85abbcfcfa45ceb8e0ea54936075f4.png

 

处理如下, 通过 startBgsaveForReplication 进行逻辑上的分发 

是 dump 内存快照文件, 还是 dump内存快照直接通过 tcp 传输数据 

52f259ff5fdc4f738f35bd2887180487.png

 

然后这里就是 fork 出子进程, 让子进程 来 dump 内存快照, 并保存到目标文件 

b8228fd2a58f4d5eaf6e17f268540803.png

 

然后 master 这边有定时任务在定时检查 子进程是否完成, 周期为 1秒 

如果完成了, 则向 slave 这边传输 dump 的内存快照的数据 

917c4dbcf0904cc08b352d0337f836ea.png

 

master 这边日志如下 

slave 这边发送过来了 PSYNC 的请求 

然后 master 这边判断 replyid, replyid2 匹配不上, 然后开始进行 全量同步 

然后 master 开始进行 dump 内存快照, fork 子进程 来生成 dump.rdb

master dump 内存快照生成完成之后, 发送数据到 slave, 之后记录 成功日志

da60fc2fde1b4f83b00c8c124b7f8a1e.png

 

 

基于 backlog 的增量同步

master 这边添加增量命令到 backlog

命令到 server.call:3765 的时候, 会将命令添加到 backlog 队列 

其中存储的数据就是 具体的执行命令, 存储在了一个数据中, 比如这里的 “set name4 jerry17”, 会将其存储为 一个长度为3的数组, 元素分别为 [“set”, “name4”, “jerry17”]

ba04a1534ab046718c620d9d3b0cad42.png

 

具体的复制命令到 backlog 中的相关处理如下, 可以简单理解为一个 memcpy 进去, 然后更新 索引 repl_backlog_idx

a3044b1a017d43da8de3032f1f1d5aca.png

 

 

slave 这边长时间和 master 失联, 重新连接之后发送 PSYNC 增量同步请求

clusterCron 为定时任务, 定时扫描集群的状态, 如果失联了, 则重新建立连接 

同样是在 syncWithMaster 的代码中, 这里传入了 replyid 和 offset 到 master 

0c02133909a24ac9949c51dcf4be9040.png

 

 

master 这边获取增量的命令响应给客户端

比如这里传输了 134 字节的命令数据到客户端, 我们 再来看一下 详细的命令信息

b3fae4214f3e40d9bb2df8f977400e62.png

 

从响应的字符串信息中可以看到, 传输了 “select 0”, “set name4 jerry18”, “set name4 jerry19”, “set name4 jerry20” 四条命令, 其中 “select 0” 是 redis 自己增加的, 然后 其他的几个命令是 客户端这边交互产生的

d264df34188742058d2ec667e97c961a.png

 

 

slave 这边收到命令之后执行

客户端这边接收到这一批次的命令之后, 依次进行执行 “select 0”, “set name4 jerry18”, “set name4 jerry19”, “set name4 jerry20” 进而实现了增量的同步 

f02dc9a1337142dbb429264788559fde.png

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/250924.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[c++]—vector类___提升版(带你了解vector底层的运用)

我写我 不论主谓宾 可以反复错 🌈vector的介绍 1.vector是表示可变大小数组的序列容器2.就像数组一样,vector也采用的连续存储空间来存储元素,也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组&…

工业性能CCD图像处理+

目录 硬件部分 ​编辑 软件部分 CCD新相机的调试处理(更换相机处理,都要点执行检测来查看图像变化) 问题:新相机拍摄出现黑屏,图像拍摄不清晰,(可以点击图像,向下转动鼠标的滚轮&#xff08…

nlp与cv的发展

Transformer的出现,促进了更高容量模型的建立,为大模型的出现奠定基础. 🧐大模型通常具有十亿个以上参数(仅供参考) 😮左边的蓝色是CV领域、右下绿色是NLP、右上蓝色是多模态😃基础模型(Foundational Models)首次由Bommasani等人在《Stanford…

算法--数据结构基础

文章目录 数据结构单链表栈表达式求值前缀表达式中缀表达式后缀表达式 队列单调栈单调队列KMPTrie并查集堆哈希表字符串哈希 数据结构 单链表 用数组模拟(静态链表)效率比定义Node类(动态链表)效率高些 使用数组模拟单链表&am…

2023年总结,讲讲我的故事吧,十年

文章目录 2023前十年后十年 周末,本该是提升自己的最好时机,也该是出去玩的大好时光,但是毫无意外的,在家躺了一天,单纯的有点累。 2023年,发生了好多事情,又好像没发生几件事,可能毕…

插入排序:直接插入排序 希尔排序

插入排序: 假设红竖线前的元素全部排好序,红线后面的数即为要插入的数据,红线依次往后移,假设end为排好序的最后一个数字,end1即为要插入的数字,一次插入时,end与要插入的数字依次比较&#xf…

springMVC-Restful风格

基本介绍 REST:即Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用. 1.HTTP协议里面,四个表示操…

Java技术栈 —— 微服务框架Spring Cloud —— Ruoyi-Cloud 学习(二)

RuoYi项目开发过程 一、登录功能(鉴权模块)1.1 后端部分1.1.1 什么是JWT?1.1.2 什么是Base64?为什么需要它?1.1.3 SpringBoot注解解析1.1.4 依赖注入和控制反转1.1.5 什么是Restful?1.1.6 Log4j 2、Logpack、SLF4j日志框架1.1.7 如何将项目打包成指定bytecode字节…

ValueError: setting an array element with a sequence...

报错:ValueError: setting an array element with a sequence… 案例1:numpy库使用numpy.array转换list a是一个list,其包含两个元组,使用np.array进行转换,会报错: import numpy as np a ([([1, 2, 3]…

nodejs微信小程序+python+PHP的微博网络舆情分析系统-计算机毕业设计推荐

(4)微博信息交流:在首页导航栏上我们会看到“微博信息交流”这一菜单,我们点击进入进去以后,会看到所有管理员在后台发布的交流信息; (5)新闻资讯:用户可以查看新闻资讯信…

关于“Python”的核心知识点整理大全24

10.1.6 包含一百万位的大型文件 前面我们分析的都是一个只有三行的文本文件,但这些代码示例也可处理大得多的文件。 如果我们有一个文本文件,其中包含精确到小数点后1 000 000位而不是30位的圆周率值,也可 创建一个包含所有这些数字的字符串。…

HiveSql语法优化三 :join优化

前面提到过:Hive拥有多种join算法,包括Common Join,Map Join,Bucket Map Join,Sort Merge Buckt Map Join等;每种join算法都有对应的优化方案。 Map Join 在优化阶段,如果能将Common Join优化为…

Java 基础学习(十二)文本I/O、日期与时间API

1 文本 I/O 1.1 字符流 1.1.1 什么是字符流 在Java中,字符流是指提供了基于字符的I/O能力的API。 Java 1.0中提供的基于字节的I/O流API只能支持8位字节流,无法妥善地处理16位Unicode字符。由于需要支持Unicode处理国际化字符,因此Java 1.…

TCP/IP详解——HTTPS 协议

文章目录 1. HTTPS 协议1.1 HTTPS 原理1.2 HTTPS 过程1.3 从数据包角度看 HTTPS 交互过程1.4 常见的 HTTPS 数据包解码1.4.1 ClientHello 数据包1.4.2 ServerHello 数据包 1.5 思考 1. HTTPS 协议 1.1 HTTPS 原理 HTTPS概念 HTTPS 是以安全为目标的HTTP通道,并不…

小 cookie,大作用:探索网站中的隐私追踪器(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

持续集成交付CICD:Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前端应用的蓝绿发布

目录 一、实验 1.蓝绿发布准备 2.Jenkins使用GitLab共享库实现基于Ansible的CD流水线部署前端应用的蓝绿发布 二、问题 1.手动构建Jenkins前端项目CI流水线报错 2.如何优化手动构建流水线选项参数 一、实验 1.蓝绿发布准备 (1)环境 表1 蓝绿发布…

flume:Ncat: Connection refused.

一:nc -lk 44444 和 nc localhost 44444区别 nc -lk 44444 和 nc localhost 44444 是使用 nc 命令进行网络通信时的两种不同方式。 1. nc -lk 44444: - 这个命令表示在本地监听指定端口(44444)并接受传入的连接。 - -l 选项…

前端视角看 Docker : 基础命令全面指南

引言 Docker是一种开源的容器化平台,它允许开发者将应用程序和其依赖打包在一个轻量级的、可移植的容器中。这使得应用程序在不同的环境中部署变得简单且高效。本文将介绍Docker的一些基础命令和概念,帮助初学者快速上手。 1. Docker简介 Docker使用…

054:vue工具 --- BASE64加密解密互相转换

第054个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…

云原生之深入解析使用Telepresence轻松在本地调试和开发Kubernetes应用程序

一、 准备 telepresence 下载:https://www.telepresence.io/docs/latest/install/kubectl 下载:https://kubernetes.io/docs/tasks/tools/ 二、版本检测 $telepresence version Client: v2.5.3 (api v3) Root Daemon: not running User Daemon: not r…