首页 > 数据库 >Redis设计与实现—复制原理

Redis设计与实现—复制原理

时间:2023-02-24 21:26:31浏览次数:35  
标签:Redis 偏移量 命令 同步操作 复制 服务器 缓冲区 原理

前言

Redis 中的复制命令原理


@

目录

Redis中可以通过 SLAVEOF 命令来设置一个服务器为从服务器,从而复制指定的主服务器的数据。

一、旧版复制原理

旧版复制功能包括 同步(sync) 和 命令传播 两个操作。

1.1 同步

从服务器对主服务器的同步操作需要发送 SYNC 命令来实现,该命令的执行步骤包括:

  1. 从服务器向主服务器发送SYNC命令;
  2. 主服务器接收到命令后,执行 BGSAVE 命令,在后台生成一个 RDB 文件,并使用一个缓冲区来记录从当前开始的写命令;
  3. 当主服务器的 BGSAVE 命令执行完成后就将 RDB 文件发送给从服务器,从服务器开始接受并且载入这个 RDB 文件;
  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器执行,从服务器来将自己的数据库状态更新为主服务器的状态。

1.2 命令传播

在同步操作完成后,主服务器一旦有一些新命令的执行导致数据库发生改变就需要将改变立刻同步到从服务器,因此对于会导致数据库更改的命令,主服务器会同样发送到从服务器。

1.3 旧版复制的缺陷

在Redis中的复制可以分为初次复制和断线后的重复制。旧版复制对于初次复制没有问题,但是断线后的重复制效率比较低。
因为当复制过程中出现断线后,当从服务器再次连接上时由于没有记录上次的复制位置,所以需要重新从头开始复制,执行 SYNC 命令(初次复制)。
但是主从服务器断开的时间比较短,导致主服务器在断线期间执行的写命令较少,而每次断线时为了这点命令选择执行 SYNC 命令,效率非常低效。

SYNC 命令是一种非常耗时的操作

  • 主服务器要执行 BGSAVE 指令来生成 RDB 文件,这个操作会消耗主服务器大量的 CPU、内存和磁盘 I/O 资源;
  • 主服务器将 RDB 文件发送到从服务器会消耗网络资源‘
  • 从服务器接受 RDB 文件后会载入,这个期间从服务器会阻塞没有办法处理命令请求。

二、新版复制原理

新版复制采用 PSYNC 命令代替旧版的 SYNC 命令。

该命令包含两个部分:

  • 完整重同步:和旧版复制的初次复制操作一样。
  • 部分重同步:用于断线后的处理,采用 复制偏移量、复制积压缓冲区、服务器运行ID来实现搞笑的重连接复制操作。

2.1 部分重同步

2.1.1 复制偏移量

在这里插入图片描述

主服务器和从服务器各保存一份复制偏移量,每次主服务器发送数据和从服务器成功接受数据就增加相应的偏移量。通过复制偏移量能够确保主从服务器的数据状态是否一致。

2.1.2 复制积压缓冲区

在这里插入图片描述
复制积压缓冲区的特点:

  • 复制积压缓冲区是由主服务器维护的一个固定长度的先进先出队列,默认大小为 1MB。
  • 每当主服务器进行命令传播时,它不仅会将数据发送给从服务器,还要将数据写入到复制积压缓冲区中,复制积压缓冲区同时还会为队列中的每个字节记录相应的复制偏移量。
  • 那么当从服务器断线重连后,它会将自己的复制偏移量发送给主服务器,主服务器就会检查该偏移量之后的数据是否全部存在于复制积压缓冲区中,如果全部存在就执行部分重同步操作;否则必须执行完整重同步操作。

复制积压缓冲区大小可以动态调整:

  • 默认大小是 1MB,但是如果断线时间过长,断线时写入的数据较多,就会由于缓冲区大小太小而不得不进行完整重同步操作。
  • 缓冲区大小的计算公式:second * write_size_per_second 来估算,second 表示从服务器断线后重新连接上主服务器所需的时间;write_size_per_second 表示主服务器每秒钟写入的命令数据量。
  • 可以通过修改配置文件中的 repl-backlog-size 选项调整缓冲区大小;通过 repl-backlog-ttl 调整缓冲区的存活时间,超过会被销毁。

2.1.2 服务器ID

每个服务器启动时都会分配一个服务器ID,当从服务器对主服务器进行初次同步操作时,主服务器会将自己的服务器ID发送给从服务器,从服务器会保存起来。
如果从服务器断开后重连到一个主服务器,它会发送之前保存的主服务器ID,如果ID和当前主服务器ID相同就执行部分重同步操作,否则执行完整重同步操作。

2.2 PSYNC 命令的实现

从服务器发送指令:

  • 如果从服务器初次同步主服务器,它会发送 PSYNC ? -1 命令,请求完整重同步操作;
  • 如果从服务器已经复制过某个主服务器后,当它开始一次新复制时会发送 PSYNC <runid> <offset> 命令,runid 是上次主服务器的ID, offset 是自己当前的复制偏移量。

主服务器回复指令:

  • +FULLRESYNC <runid> <offset>:主服务器与从服务器执行完整的重同步操作;
  • +CONTINUE:执行部分重同步操作,等待主服务器发送数据;
  • -ERR:识别不了命令,出现问题。

三、复制的实现

3.1 从服务器保持主服务器的地址和端口

当客户端向从服务器发送 slave of xxx xxx 命令时,从服务器将主服务器的 ip地址和 port端口保存到 redisServer 中的 masterhostmasterport 属性中。

3.2 建立套接字连接

从服务器建立套接字来连接到主服务器,如果连接成功,从服务器会为这个套接字关联一个专门用于处理复制工作的文件事件处理器,这个处理器将负责执行后续的复制工作。
主服务器在接受从服务器的套接字连接后,将为该套接字建立客户端状态,并将从服务器看作是一个连接到主服务器的客户端来看待。

3.3 发送PING命令

从服务器发送一个 PING 命令来保证主从服务器双方读写状态是否正常。

3.4 身份认证

如果主服务器设置了 requirepass 并且从服务器设置了 masterauth,需要进行身份认证。

3.5 发送端口信息

身份认证后,从服务器会执行命令 REPLCONF listening-port <port-number> 来向主服务器发送自己监听的端口号方便后续通信。
主服务器接受后会保存到 slave_listening_port 属性中。

3.6 同步

从服务器向主服务器发送 PSYNC 命令,执行同步操作,并将自己的数据库更新。
注意在同步操作前只有从服务器是主服务器的客户端,而同步操作以后主从服务器都是对方的客户端和服务器,因为它们可以向对方发送命令请求或者互相向对方回复命令。

3.7 命令传播

一直执行,保证双方数据同步。


四、心跳检测

发生在命令传播阶段,从服务器会每隔1s 向主服务器发送命令 REPLCONF ACK <replication_offset> ,其中 replication_offset 是从服务器当前的复制偏移量。

心跳检测的作用

1) 检测主从服务器的网络状态

如果主服务器超过1s 没有接收到从服务器的 REPLCONF ACK 命令,就知道之间的连接出现了问题。可以通过 info replication 命令来查看:
在这里插入图片描述
lag 表示距离上一次接收到从服务器的心跳检测过去了多长时间。

2) 辅助实现 min-slaves配置选项

min-slaves-to-write:从服务器的最少数量,少于这个标准主服务器会拒绝执行写命令;
min-slaves-max-lag:心跳延迟最大值。

3) 检测命令丢失

由于从服务器发送时会携带上自己的复制偏移量,主服务器就可以在接受心跳检测时检查自己的复制偏移量是否同步,如果发现从服务器的复制偏移量小了,就将复制积压缓冲区里面的数据发送给从服务器。

标签:Redis,偏移量,命令,同步操作,复制,服务器,缓冲区,原理
From: https://www.cnblogs.com/istitches/p/17153178.html

相关文章

  • Redis设计与实现—简单动态字符串、链表、字典
    前言《Redis设计与实现》数据结构部分有关字符串类型介绍。@目录前言一、数据结构——简单动态字符串1.1SDS定义1.2SDS与C字符串的区别1.2.1常数复杂度获取字符串长度......
  • Redis设计与实现—事件机制
    前言Redis内部消息通信机制学习和了解@目录前言一、Redis中事件的分类文件事件文件事件处理器I/O多路复用程序的实现文件事件处理器时间事件时间事件怎么处理关键的时......
  • Redis设计与实现—数据库与过期键策略
    前言深入了解一下Redis内存机制如何存储数据,以及对于过期数据采取何种策略来清理。@目录前言一、Redis服务器中的数据库二、数据库键空间2.1数据存储——键空间dict2.......
  • Redis设计与实现—跳跃表、压缩列表
    前言Redis设计与实现读书笔记,基础数据结构部分——跳跃表与压缩列表@目录前言一、跳跃表1.1跳跃表概念1.2Redis中跳跃表的实现1.3跳跃表节点(zskipListNode)1.4手动......
  • Mysql、(八) 主从复制
    @目录一、MySQL主从复制步骤二、主从复制的配置主机的配置从机的配置其它操作一、MySQL主从复制步骤Master将改变记录到二进制日志(binarylog)。这些记录过程叫做二......
  • redis(4)String字符串
    前言Redis中有5大数据类型,分别是字符串String、列表List、集合Set、哈希Hash、有序集合Zset,本篇介绍Redis的字符串String Redis字符串String是Redis最基本的类型,你可......
  • Nginx+Tomcat+Redis实现负载均衡会话保持
    Nginx+Tomcat+Redis实现负载均衡会话保持......
  • 【JavaScript】27_浅拷贝和深拷贝 + 对象的复制
    7、浅拷贝和深拷贝浅拷贝(shallowcopy)通常对对象的拷贝都是浅拷贝浅拷贝顾名思义,只对对象的浅层进行复制(只复制一层)如果对象中存储的数据是原始值,那么拷贝的深浅是不重要浅......
  • 一文带你了解线程池原理
    一文带你了解线程池原理1.使用线程池的意义何在?​ 项目开发中,为了统一管理线程,并有效精准地进行排错,我们经常要求项目人员统一使用线程池去创建线程。因为我们是在受不......
  • 定时任务原理方案综述
    定时任务原理方案综述https://mp.weixin.qq.com/s/u6EFPVql4IuoG9-NJLDhsA定时任务原理方案综述原创 肖明睿 京东技术 2023-02-2319:00 发表于北京 Tech导读......