当前位置: 首页 > news >正文

【Redis-08】Redis主从复制的实现原理

 在Redis中,可以通过slaveof命令或者设置slaveof选项实现两台Redis服务器的主从复制,比如我们有两个Redis机器,地址分别是 127.0.0.1:6379 和 127.0.0.1:6380,现在我们在前者上面执行:

127.0.0.1:6379 > SLAVEOF 127.0.0.1:6380

 那么,127.0.0.1:6379就会成为从服务器,127.0.0.1:6380就是主服务器,主从服务器通过复制会保存相同的数据,这就是数据库状态一致。今天我们探讨的重点是,主从服务器之间是如何实现数据复制的,以及slaveof这个命令的实现原理。

1.全量复制功能的实现

 主从复制的实现是通过两个操作来实现的,分别是同步(sync)和命令传播(propagate),我们看着这两个操作代表什么含义:

  • 同步:将从服务器的状态更新至主服务器当前所处的数据库状态;这里会通过一个SYNC命令来完成,具体如下:
    1. 从服务器发送SYNC命令给主服务器;
    2. 主服务器接收到命令,执行bgsave命令,创建RDB文件;
    3. 主服务器记录bgsave命令执行期间处理的客户端新命令,并写入到某个缓冲区中;
    4. RDB文件创建完成,主服务器发送给从服务器,从服务器完成RDB文件的载入;
    5. 主服务器将命令缓冲区的内容发给从服务器,从服务器执行所有命令;
    6. 从服务器状态与主服务完成数据库状态一致。
      在这里插入图片描述
  • 命令广播:主服务器会将自己执行的写命令,发送给从服务器执行,使得两者再次保持状态一致。

2.增量复制功能的实现

 主从复制分为初始化复制和断线后复制,即从服务器初始启动时,执行saveof命令会执行一次同步,还有从服务器断线后再次链接,也会执行一次同步。

 在早起的Redis的版本中,无论是首次启动还是断线后重连,都是适用SYNC命令实现,即:全量复制,但是SYNC是一个特别耗费资源的操作,会占用大量CPU、内存、网络和磁盘I/O的资源,所以在后期的版本中,是使用增量复制PSYNC来实现复制操作的。

PSYNC这个命令是同时具有完整同步和部分重同步的功能,其中完整同步的功能和SYNC命令执行的步骤一样,而部分重同步的功能是在服务器断线重连后,如果条件允许,主服务器将断线期间的命令发送给从服务器执行,达到状态的同步的目的。所以这种部分重同步的操作相对于完整同步,是能减少很多资源消耗的。

2.1 部分重同步的实现细节

 部分重同步的功能是通过3个部分构成的,分别是主从服务器两者的复制偏移量,主服务器的复制积压缓冲区,服务器的运行ID。

2.1.1 复制偏移量

 复制的双方,分别会维护一个复制的偏移量:

  • 主服务器的复制积压缓冲区每次向从服务器传播N个字节时,就会将自己的复制偏移量 +N;
  • 从服务器在接收到N个字节数据时,会将自己的复制偏移量 +N。

 这样复制的双方就可以通过复制偏移量,达到同步的目的。如果主从服务器的状态一致,那么他们的复制偏移量总是相同的,否在是处于状态不一致的情况。

2.1.2 复制积压缓冲区

 复制积压缓冲区是由主服务器维护的一个固定长度先进先出的队列,默认大小是1MB。当服务器向从服务器传播命令时,它还会将此命令入队到复制积压缓冲区里面。同时,复制积压缓冲区会为入队的每一个字节记录相应的复制偏移量值,这里的偏移量和2.1.1维护的偏移量值是相匹配。同时由于固定队列先进先出的特性,使得复制积压缓冲区中,仅保存最近一段时间执行的同步命令。

 当服务器连接到主服务器时,从服务器向主服务器发送PSYNC命令是会带上自己的复制偏移量offset,主服务器根据此偏移量决定执行哪种操作:

  • 如果从服务器偏移量offset之后的数据还保存在主服务器的复制积压缓冲区里面,那么主服务器会执行部分重同步的操作。
  • 如果从服务器偏移量offset之后的数据已经不在主服务器的复制积压缓冲区里面了,那么主服务器会执行完整同步的操作。

 所谓的部分重同步操作,是指主服务器将从服务器偏移量offset之后的所有命令发给从服务器,避免全部命令重新发送的问题。

2.1.3 服务器运行ID

 每个Redis服务器(包括主从),都会有自己的运行ID,主从服务器首次进行同步时,主服务器会将自己的运行ID发送给从服务器,从服务器会保存此ID。
 当从服务器断线重连后,想要执行复制操作,会将前面保存的服务器ID发送给主服务器,此时由主服务器执行判断:

  • 如果从服务器保存的此ID和自己的ID相同,那说明断线前后的主服务器是同一个,此时就会根据偏移量判断是执行全部同步还是部分重同步。
  • 如果从服务器保存的此ID和自己的ID不同,那说明断线前后的主服务器已经变了,此时就会执行完整同步的操作。

3.心跳检测

 在主从复制的命令传播期间,从服务器会以每秒一次的频率,向主服务器发送命令:

REPLCONF ACK <replication_offset>

 其中,replication_offset是服务器当前的复制偏移量。那么发送此命令的作用是什么呢,主要是下面三个:

  1. 检测主从服务器之间的网络连接状态: 如果主服务器在超过1s内未收到从服务器发送的命令,就会认为两者之间的网络连接出现问题了。
  2. 辅助实现min-slaves选项: 在配置文件中,有这么两个参数,min-replicas-to-writemin-replicas-max-lag,如下,如果我们开启了此选项,表示如果从服务器数量少于3个,或者三个主从服务器之间的复制延迟都大于等于10s时,主服务器将拒绝执行写命令,这里主要是为了防止主服务器在不安全的情况下执行写命令。
# 从服务器的数量是3个
min-replicas-to-write 3 
# 主从服务器之间的延迟时间,单位是3
min-replicas-max-lag 10
  1. 检测广播命令是否丢失: 在命令广播期间,因为网路问题可能存在命令在半路丢失的情况,所以通过此命令的 replication_offset,即从服务器的复制偏移量,主服务器就可以获悉从服务器是否成功执行了上一次发送的命令。如果主从的复制偏移量相等,说明命令传播没有问题,如果不相等,说明命令有丢失或从服务器执行失败的情况,此时主服务器就会把从服务器偏移量之后的命令从新发送给从服务器执行,保证两个服务器状态的一致性。

相关文章:

  • Linux驱动开发之杂项设备注册和Linux2.6设备注册
  • Android IdleHandler闲时加载
  • 《Python机器学习原理与算法实现》学习笔记
  • redis—List列表
  • MySQL:主从复制
  • 【项目】玩具租赁博客测试报告
  • 每日一题(LeetCode)----二叉树-- 二叉树的右视图
  • 【智慧门店】东胜物联蓝牙网关助力解决方案商,推动汽车后市场企业智能化升级
  • Java:基本类型及它们的封装类
  • 复试 || 就业day05(2023.12.31)算法篇
  • SpringCloud(H版alibaba)框架开发教程,使用eureka,zookeeper,consul,nacos做注册中心——附源码(1)
  • IntelliJ IDEA [插件 MybatisX] mapper和xml间跳转
  • 【Spring Security】AuthenticationFailureHandler 用户认证失败后处理
  • 数据特征工程 | PSO粒子群算法的特征选择原理及python代码实现
  • web component - 使用HTML Templates和Shadow DOM构建现代UI组件
  • fetch 从初识到应用
  • php ci框架整合银盛支付
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Redash本地开发环境搭建
  • 安装python包到指定虚拟环境
  • 回流、重绘及其优化
  • 简单实现一个textarea自适应高度
  • 聊聊hikari连接池的leakDetectionThreshold
  • 王永庆:技术创新改变教育未来
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • AI算硅基生命吗,为什么?
  • MyCAT水平分库
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (一)为什么要选择C++
  • (译)2019年前端性能优化清单 — 下篇
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 使用配置文件
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .NET多线程执行函数
  • /dev/sda2 is mounted; will not make a filesystem here!
  • ::
  • ::前边啥也没有
  • [100天算法】-目标和(day 79)
  • [BZOJ] 3262: 陌上花开
  • [E单调栈] lc2487. 从链表中移除节点(单调栈+递归+反转链表+多思路)
  • [HCTF 2018]WarmUp (代码审计)
  • [HNOI2008]玩具装箱toy
  • [JS] 常用正则表达式集(一)
  • [LeetCode] Minimum Path Sum
  • [NHibernate]一对多关系(关联查询)
  • [NOI2005]聪聪与可可(期望)
  • [NOI2020统一省选 A] 组合数问题 (推式子)
  • [NOIP2005]过河
  • [python]python筛选excel表格信息并保存到另一个excel
  • [sd_scripts]之train