【Redis】主从复制分析-基础

1 主从节点运行数据的存储

在主从复制中, 对于主节点, 从节点就是自身的一个客户端, 所以和普通的客户端一样, 会被组织为一个 client 的结构体。

typedef struct client {// 省略
} client;

同时无论是从节点, 还是主节点, 在运行中的数据都存放在一个 redisServer 的结构体中, 定义如下:

struct redisServer {// 省略
};

在主从复制中的 client 和 redisServer 都是用来存储运行中的一些数据。
具体里面存储的数据是什么, 在后面的源码分析中, 逐渐了解。

2 主从节点复制中的状态枚举

2.1 从节点自身状态的状态枚举

整个主从复制是一个复杂的过程, 所以在从节点中, 维护了一套状态, 通过状态来判断下一步的流程 (有点像状态模式)

// 没有开启主从复制功能, 默认的状态
#define REPL_STATE_NONE 0// 开启了主从复制, 但是还没连接上主节点
// 执行了 slaveof/replicaof 命令时, 从节点的切换成的状态 
#define REPL_STATE_CONNECT 1// 正在连接主节点, 从节点开始连接主节点
#define REPL_STATE_CONNECTING 2/* --- 握手阶段的状态开始, 整个握手过程必须按照下面的顺序进行 --- */// 从节点发送了 ping, 等待主节点 pong  应答 (正常情况, 主节点会回复一个 pong)
#define REPL_STATE_RECEIVE_PONG 3// 准备发送认证密码给主节点
#define REPL_STATE_SEND_AUTH 4// 等待主节点响应认证结果应答
#define REPL_STATE_RECEIVE_AUTH 5// 准备发送从节点的监听的端口
#define REPL_STATE_SEND_PORT 6 // 等待主节点响应收到从节点端口
#define REPL_STATE_RECEIVE_PORT 7// 发送主从复制配置的监听的 IP 地址
#define REPL_STATE_SEND_IP 8 // 等待主节点响应收到从节点的 IP 地址
#define REPL_STATE_RECEIVE_IP 9// 准备发送从节点支持的同步能力 
#define REPL_STATE_SEND_CAPA 10 // 等待主节点响应收到支持的同步能力的应答
#define REPL_STATE_RECEIVE_CAPA 11// 向主节点发送 psync 命令, 请求同步复制
#define REPL_STATE_SEND_PSYNC 12 // 等待 psync 应答
#define REPL_STATE_RECEIVE_PSYNC 13/* --- 握手阶段的状态结束 --- */// 正在接收从主节点发送过来的 RDB 文件
#define REPL_STATE_TRANSFER 14 // 已经连接状态
#define REPL_STATE_CONNECTED 15 

2.2 主节点保存从节点的状态枚举

对于主节点而言, 需要知道从节点当前的状态的, 好进行对应的操作, 但是不需要那么详细, 主节点也维护了一套从节点运行时的状态


// 等待 bgsave (生成 RDB 文件的函数) 的开始
#define SLAVE_STATE_WAIT_BGSAVE_START 6// 等待 bgsave 的结束, 也就是 RDB 文件的创建结束
#define SLAVE_STATE_WAIT_BGSAVE_END 7// 发送一个 RDB 文件到从节点
#define SLAVE_STATE_SEND_BULK 8// 从节点在线
#define SLAVE_STATE_ONLINE 9

3 从节点复制能力

3.1 全量复制和部分复制

整个主从复制, 大体可以概括为 3 种情况

  1. 一开始, 主从节点建立连接, 这时候主节点需要将自身所有的数据全部同步给从节点
  2. 运行中, 主节点需要将自己处理的命令, 发送一份给从节点, 这样才能保证主从的一致
  3. 运行中, 出现了网络波动, 服务重启等情况, 重新恢复正常时, 主从需要重新通过复制, 让彼此的数据重新保持一致

第一步
主从建立了连接, 主节点会将自身所有的数据生成为一个 RDB 的文件, 然后以 EOF 的流格式发送给从节点。
当然, Redis 在 2.8.18 版本开始支持无盘复制, 子进程直接将 RDB 通过网络发送给从服务器, 不使用磁盘作为中间存储。
主要是防止比较低速的磁盘, 写入缓慢, 影响到整个应用。
这个主节点将所有数据发送给从节点的操作, 叫做全量复制

第二步
在运行中, 主节点处理完了命令, 会遍历自身维护的所有的从节点, 将自身执行的命令发送给所有状态符合的从节点, 保证数据的一致。
可以看出来, 第一, 二步的操作是一个比较简单的过程, 而第三步, 在兼容性能的情况下, 将会是一个复杂的过程。

第三步
主从节点之间出现网络波动, 从节点重启等行为后, 主从之间就可能出现数据不一致。
在 Reids 2.8 版本之前, Reids 的操作就是通过在来一次全量复制, 保证了主从节点数据的一致性。

全量复制 我们可以很容易就想到这是一个耗时, 耗资源的过程, 比如 fork 子进程, RDB 文件生成, 数据发送。
所以为了尽量避免全量复制的出现, 在 Redis 2.8 版本, 引入了一个复制积压缓冲区的缓存区, 主节点执行的命令, 会先保存一份到这个缓存区
(这个缓存区是一个环形的数组, 从头写到尾, 写满了, 重新回到头, 继续写, 新的数据覆盖掉旧的, 同时所有的从节点共用一个缓冲区)。

Alt '复制积压缓冲区'

大体的实现如下

  1. 主节点启动的时候, 会生成一个 run_id (用来确保复制的主节点的唯一性)
  2. 同时生成一个复制积压缓冲区, 并且有一个变量, 记录着缓冲区中当前最旧的数据的位置, 假设为 min, 假设复制积压缓冲区的容量为 len
  3. 从节点保存着主节点生成的 run_id, 同时维持着一个变量, 当前自身最新的数据在复制积压缓冲区的哪个位置, 也就是复制偏移量, 假设为 offset
  4. 当前主从复制出现问题时, 主从重新建立连接后, 从节点会将 run_id 和 offset 发送给主节点
  5. 主节点收到后, 如果 run_id 和自身的一致, 同时 min <= offset <= min + len, 也就是需要开始复制的位置的数据, 可以在缓存区中找到, 那么从这个位置进行部分复制
  6. 主节点如果收到的 run_id 不一致, 或者 offset < min 或者 offset > min + len, 也就是需要开始复制的位置不在缓冲区中, 直接进行全量复制

Alt '部分复制过程'

这个的功能叫做 psync, 可以理解为 部分复制, 这个功能可以减少全量复制的发生。
但是这个功能有些问题, 就是从节点需要维护好 run_id, run_id 需要和从节点的一致, 同时 offset 需要在复制积压缓存中, 这其中

  1. slave 维护性重启, run_id 和 offset 会丢失
  2. 主节点故障转移, run_id 会改变
    都会导致从节点直接全量复制

所以在 Redis 4.0 针对上面的 2 种情况进行了优化, 使其在上面说的情况下, 可以进行使用部分复制, 这个升级的功能也被叫做 psync2
涉及的几个名词

  1. replid1, 每个 Redis 实例启动就会自动产生的一个 id, 这个实例变成从节点, 会被替换为主节点的 replid1
  2. replid2, 默认初始为 0, 用于存储上次主节点的 replid1

当然还要其他的情况, 会导致部分复制的失效

  1. 直接重启主节点, 这是复制积压缓冲区的数据丢了, 没法部分复制

所以 psync2 只是针对上面的 2 种情况进行了优化, 其他的情况, 还是会直接进入到全量复制

3.2 从节点重启的部分复制

在 Redis 4.0 中

  1. Redis 关闭时, 会把复制相关的信息 replid1 和 offset 作为辅助信息保存到 RDB 文件
  2. Redis 重启时, 会将从 RDB 文件中重新加载对应的复制信息到对应的字段
  3. 在进行同步时, 将 replid 和 offset 发送给主节点, 尝试进行部分复制
3.3 主节点故障转移的部分复制

当前的场景主要是在 Redis Cluster 中的故障转移情景的分析, 在直接使用主从复制中, 主节点重启, 挂了等, 都无法避免全量复制

在 Redis 4.0 中

  1. 使用了 2 组 replid 和 offset
  2. 从节点也会开启复制积压缓冲区功能, 以便从节点故障切换变化为主节点后, 其他落后的从节点可以进行同步
  3. 第一组 replid 和 offset, 如果是主节点, 表示的是自己的 replid 和复制偏移量 offset, 从节点表示的是主节点的 replid (确保级联时, replid 都是一致的) 和自身同步主节点的赋值偏移量
  4. 第二组 replid 和 offset, 无论是主从, 都表示自己的上次主节点的 replid 和 offset, 没有则默认为 0 和 -1
  5. 主节点发生了故障切换时, 会将自身的第一组 replid 和 offset 复制给第二组 replid 和 offset
  6. 这时候, 无论是一主一次还是一主多从, 都会有一个自身的从节点变为主节点, 自身变为从节点, 后面故障恢复了, 可以根据自身的第二组 replid 和 offset 进行恢复
  7. 当然不只是主从关系, 级联复制, 也适用

上面说的 3 个版本的复制能力, 在代码中分别叫做 EOF, psync1, psync2

复制能力的定义如下:

// 什么能力都不支持
#define SLAVE_CAPA_NONE 0// 支持 EOF, 支持全量复制, 可以解析 RDB EOF 流式处理格式
#define SLAVE_CAPA_EOF (1<<0) // 支持 psync2, 支持部分复制
#define SLAVE_CAPA_PSYNC2 (1<<1)

对于 Redis 从节点, 可能因为版本问题, 存在着复制能力不一致的情况, 所以在主从复制开始的阶段, 从节点需要将自身支持的复制能力发送给主节点,
主节点才能以正确的方式同步数据给从节点。

4 参考

redis psync1和psync2 同步详解

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用C#手搓Word插件

WordTools主要功能介绍 编码语言&#xff1a;C#【VSTO】 1、选择 1.1、表格 作用&#xff1a;全选文档中的表格&#xff1b; 1.2、表头 作用&#xff1a;全选文档所有表格的表头【第一行】&#xff1b; 1.3、表正文 全选文档中所有表格的除表头部分【除第一行部分】 1.…

Vue常用指令及其生命周期

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 目录 1.常用指令 1.1 v-bind 1.2 v-model 注意事项 1.3 v-on 注意事项 1.4 v-if / v-else-if / v-else 1.5 v-show 1.6 v-for 无索引 有索引 生命周期 定义 流程 1.常用指令 Vue当中的指令…

福派斯牛肉高脂猫粮,为何成猫舍首选?揭秘其神奇功效!

&#x1f43e; 说到猫咪的伙食&#xff0c;咱们当铲屎官的可是操碎了心&#xff01;想让自家毛孩子吃得健康又开心&#xff0c;选对猫粮真的太重要了。今天就来聊聊为啥福派斯牛肉高脂猫粮能成为众多猫舍的首选&#xff0c;以及它到底能帮咱们的小猫咪哪些忙吧&#xff01; 1️…

数据传输安全--SSL VPN

目录 IPSEC在Client to LAN场景下比较吃力的表现 SSL VPV SSL VPN优势 SSL协议 SSL所在层次 SSL工作原理 SSL握手协议、SSL密码变化协议、SSL警告协议三个协议作用 工作过程 1、进行TCP三次握手、建立网络连接会话 2、客户端先发送Client HELLO包&#xff0c;下图是包…

springboot项目从jdk8升级为jdk17过程记录

背景&#xff1a;公司有升级项目jdk的规划&#xff0c;计划从jdk8升级到jdk11 开始 首先配置本地的java_home 参考文档&#xff1a;Mac环境下切换JDK版本及不同的maven-CSDN博客 将pom.xml中jdk1.8相关的版本全部改为jdk17&#xff0c;主要是maven编译插件之类的&#xff0c…

ubuntu22.04 安装 NVIDIA 驱动以及CUDA

目录 1、事前问题解决 2、安装 nvidia 驱动 3、卸载 nvidia 驱动方法 4、安装 CUDA 5、安装 Anaconda 6、安装 PyTorch 1、事前问题解决 在安装完ubuntu之后&#xff0c;如果进入ubuntu出现黑屏情况&#xff0c;一般就是nvidia驱动与linux自带的不兼容&#xff0c;可以通…

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过&#xff0c;晚上有面试&#xff0c;今天水一水。 第一题&#xff1a;Leetcode77. 组合 题目描述 解题思路 从题目示例来看&#xff0c;k个数是不能重合的&#xff0c;但是题目没有明确说明这一点。 使用回溯算法解决此问题&#xff0c;利用树形…

数据结构 —— B+树和B*树及MySQL底层引擎

数据结构 —— B树和B*树及MySQL底层引擎 B树B*树B树的应用B树在MySQL中的应用MyISAMInnoDB 我们之前学习了B树的基本原理&#xff0c;今天我们来看看B树的一些改良版本——B树和B*树。如果还没有了解过的小伙伴可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/ar…

【MySQL进阶之路 | 高级篇】MVCC三剑客:隐藏字段,Undo Log,ReadView

1. 再谈隔离级别 我们知道事务有四个隔离级别&#xff0c;可能存在三种并发问题&#xff1a; 在MySQL中&#xff0c;默认的隔离级别是可重复读&#xff0c;可以解决脏读和不可重复读的问题&#xff0c;如果仅从定义的角度来看&#xff0c;它并不能解决幻读问题。如果我们想要解…

Nacos-2.4.0最新版本docker镜像,本人亲自制作,部署十分方便,兼容postgresql最新版本17和16,奉献给大家了

基于Postgresql数据库存储的nacos最新版本2.4.0,采用docker镜像安装方式 因业务需要,为了让nacos支持postgresql,特意花了两天时间修改了源码,然后制作了docker镜像,如果你也在找支持postgresql的nacos最新版本,恭喜你,你来的正好~ nacos-2.4.0 postgresql的数据库脚本…

安宝特方案|解放双手,解决死角,AR带来质量监督新体验

AR质量监督 解放双手&#xff0c;解决死角 在当今制造业快速发展的背景下&#xff0c;质量监督成为确保产品高质量和完善的管理制度的关键环节。然而&#xff0c;传统的质量监督方式存在诸多挑战&#xff0c;如人工操作带来的效率低下、查岗不及时、摄像头死角等问题。 为了解…

本地部署,Whisper: 开源语音识别模型

目录 简介 特点 应用 使用方法 总结 GitHub - openai/whisper: Robust Speech Recognition via Large-Scale Weak SupervisionRobust Speech Recognition via Large-Scale Weak Supervision - openai/whisperhttps://github.com/openai/whisper 简介 Whisper 是一个由 O…

GoogleCTF2023 Writeup

GoogleCTF2023 Writeup Misc NPC Crypto LEAST COMMON GENOMINATOR? Web UNDER-CONSTRUCTION NPC A friend handed me this map and told me that it will lead me to the flag. It is confusing me and I don’t know how to read it, can you help me out? Attach…

软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策

引言 原文链接 近日&#xff0c;一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新&#xff0c;如同一颗隐形炸弹在全球范围内引爆&#xff0c;…

17.5【C语言】static的补充说明

static &#xff08;静态的) 作用&#xff1a;修饰局部变量&#xff0c;修饰全局变量&#xff0c;修饰函数 对比两段代码 #include <stdio.h> void test() {int a 5;a;printf("%d ", a); } int main() {int i 0;for(i0; i<5; i){test();}return 0; } …

高并发内存池——链表设计

自由链表类的设计 由于申请的空间块经过对齐之后大小至少为8&#xff0c;因此可以考虑在未被使用的内存块中取前8字节存储下一个空间的地址 FreeList类初步声明 class FreeList { private:void* _freelistnullptr; //自由链表头指针size_t _size0; //自由链表的长度size_t …

【Django】anaconda环境变量配置及配置python虚拟环境

文章目录 配置环境变量配置python虚拟环境查看conda源并配置国内源在虚拟环境中安装django 配置环境变量 control sysdm.cpl,,3笔者anaconda安装目录为C:\ProgramData\anaconda3 那么需要加入path中的有如下三个 C:\ProgramData\anaconda3 C:\ProgramData\anaconda3\Scripts C:…

最新风车IM即时聊天源码及完整视频教程2024年7月版

堡塔面板 试验性Centos/Ubuntu/Debian安装命令 独立运行环境&#xff08;py3.7&#xff09; 可能存在少量兼容性问题 不断优化中 curl -sSO http://io.bt.sy/install/install_panel.sh && bash install_panel.sh 1.宝塔环境如下: Nginx 1.20 Tomcat 8 MySQL 8.0 R…

Java 开发环境配置

1. 下载 JDK 直接在oracle 官网下载 https://www.oracle.com/java/technologies/downloads或者使用博主已经从oracle下载的 jdk21&#xff1a;https://download.csdn.net/download/u011171506/89585231jdk8&#xff1a;https://download.csdn.net/download/u011171506/8958523…

快醒醒,别睡了!...讲《数据分析pandas库》了—/—<4>

一、废话不多说&#xff0c;直接开讲 1、DataFrame的索引和切片 1.1 选择列 当想要获取 df 中某列数据时&#xff0c;只需要在 df 后面的方括号中指明要选择的列即可。如果是 一列&#xff0c;则只需要传入一个列名;如果是同时选择多列&#xff0c;则传入多个列名即可&#xf…