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

Redis 主从复制

分布式系统

Redis 主要运用于 分布式系统,其中涉及到一个非常关键的问题:单点问题 ——>

如果某个服务器程序,只有一个节点(只有一个物理服务器,来部署服务器程序)

1)可用性问题,如果这个机器挂了,服务也就中断了

2)性能 / 支持的并发量是比较有限的

引入分布式系统,主要也是解决上述的单点问题 ——>

在分布式系统中,一般希望有多个服务器来部署 Redis 服务,从而构成一个 Redis 集群

此时,可以让这个集群给整个分布式系统中的其他服务,提供更稳定 / 更高效的数据存储功能

在分布式系统,使用多个服务器部署 Redis 方式,存在以下几种:

1)主从模式

2)主从 + 哨兵模式

3)集群模式

主从复制作用

在若干个 Redis 服务器中,有一个是“主节点”,其余的是“从节点”

从节点上的数据跟随主节点变化,从节点的数据要和主节点保持一致

例如,在主节点上有一些数据,引入从节点后,需要把主节点上的数据复制放到从节点上。后续主节点这边对数据的修改,会同步到从节点上(从节点相当于是主节点的副本)

Redis 主从模式中,从节点上的数据不允许从客户端修改,只能读取数据

主从模式,主要是针对“读操作”进行 并发量&可用性 的提高

对于写操作,无论是可用性还是并发量,都非常依赖主节点(主节点只有一个)

对于单个 Redis 服务器节点,机器挂了,整个 Redis 也就挂了

对于主从结构,可以把机器放到不同机房(异地多活)

在主从结构中,如果从节点挂了,其余从节点可以继续从主节点或者其他从节点获取数据,效果完全相同

如果主节点挂了,从节点只能读数据,如果需要写数据,就不能进行

由于从节点的数据都是实时与主节点保持一致的

在从节点和主节点中读取数据,是没有区别的

此时引入了更多的计算资源,能支撑的并发量也大幅提高

相关配置

配置 Redis 主从结构,需要启动多个 Redis 服务器

正常来说,每个 Redis 服务器程序,应该在一个单独的主机上(分布式)

但考虑到现在我们只有一个云服务器,可以在一个云服务器上,运行多个 redis-server 进程

redis-server 的默认端口是 6379

此时需要保证多个 redis-server 的端口是不同的 ——>

1)在启动程序的时候,通过命令行指定端口  --port

2)在配置文件中,设置端口

配置多个 Redis 服务器

此处准备了一个主节点,两个从节点

主节点的配置不需要改变,只需要改变从节点即可

1)修改 端口号,避免端口号冲突

2)按照后台进程的方式运行

启动 新复制的节点

此时只是创建了两个从节点,并未形成主从关系

配置 主从结构

1)在配置文件中加入 slaveof{masterHost}{masterRort},随 Redis 重启生效

2)在 redis-server 启动命令时加入  --slaveof{masterHost}{masterPort},随 Redis 重启生效

3)直接使用 redis 命令:slaveof{masterHost}{masterPort} 直接生效

此处以 配置文件中的操作为例 1),持久有效

Redis 服务器的配置文件修改完后,需要从新启动才能生效

1)kill -9 进程号,这种结束 redis-server 的方式,和直接运行 redis-server 命令式搭配的

2)service redis-server start 启动,对应 service redis-server stop 停止

在2)时,使用 kill -9 命令停止,redis-server 进程能自动启动

守护线程:专门监视指定的服务器进程的运行状态,确保服务器的稳定性和高可用性

新开一个 redis 客户端,开启 从节点

主节点和从节点之间的 TCP 连接,从节点启动后会和主节点建立 TCP 连接

此时,主节点相当于是服务器,从节点相当于是客户端

只能读,不能写

查看主从结构信息

主节点:

offset  相当于是从从节点和主节点之间,同步数据的进度

主节点会一直接收数据,从节点需要从主节点同步数据,此处的数据同步不是瞬间完成的

积压缓冲区

从节点:

从节点也可以配置从节点

断开主从结构

slaveof no one  在 Redis 客户端的命令

断开现有的主从复制关系,从节点抛弃主从结构,但是已有的数据不会抛弃

以上的修改时临时性,如果 Redis 重启,任然会按照配置文件中的内容来建立主从关系

安全

主节点可以设置 requirepass 参数进行密码验证

此时所有的客户端访问必须使用 auth 命令进行验证

从节点与主节点的复制连接是通过一个特殊标识的客户端来完成的,因此需要配置从节点 masterauth 参数与主节点密码保持一致,从节点才可以正确连接到主节点并发起复制连接

只读

默认,从节点使用 slave-read-only=yes

如果允许从节点修改,后续从节点进行的修改,主节点是感知不到的

传输延迟

主节点和从节点通过网络来传输(TCP)

TCP 内部支持 nagle 算法(默认开启)

开启时,增加 TCP 的传输延迟,节省网络带宽

目的和 TCP 的捎带应答一样

针对较小的 TCP 数据报,进行合并,减少包的个数

real-disable-tcp-nodelay  该选项可以在主从通信过程中,关闭 tcp 的 nagle 算法

从节点可以与主节点更快的进行同步

拓扑结构

若干个节点之间,进行组织连接的方式

一主一从

主节点执行读操作和写操作,从节点执行写操作

当请求数量太多 ——> 可以关闭主节点的 aof 文件,只开启从节点上的 aof 文件

当主节点挂了,不能让主节点自动启动

没有 aof 文件,重启会丢失数据。一旦主从同步,从节点上的数据也会被删 ——>

当主节点挂了,让 主节点 从 从节点 获取 aof 文件,再启动

一主多从

主节点上的数据发生改变,会把改变的数据同时同步给所有的从节点

随着从节点的个数增加,同一条数据需要传输多次

树状主从 

主节点消耗的网络带宽减少

但是修改数据,同步时的延迟是比之前长的

基本流程

1)开始配置主从同步关系后,从节点只保存主节点的地址信息,此时建立复制的流程还没开始

从节点中保存,主节点的 ip 和 port ,但是主节点的连接状态(master-link-status)是下线状态

2)从节点内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现新的主节点后,会尝试与主节点建立基于 TCP 的网络连接。如果从节点无法建立连接,定时任务会无限重试直至建立成功或者用户停止主从复制

3)建立连接成功后,从节点通过 ping 命令确认主节点在应用层上是工作良好的

如果 ping 命令的结果 pong 回复超时,从节点会断开 TCP 连接,等待定时任务下次重新建立连接

4)如果主节点设置 requirepass 参数,需要密码验证

从节点通过配置 masterauth 参数来设置密码。如果验证失败,则从节点的复制会停止

5)对于首次建立复制的场景,主节点会把当前持有的所有数据全部发给从节点,这步操作基本是耗时最长的(全量复制)

6)当从节点复制了主节点的所有数据后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执行修改命令,保证主从数据的一致性(增量复制)

TCP 三次握手,验证通信双方是否能正确读取数据(系统层面)

3)发送 ping 命令,验证主节点能否正常工作

数据同步

psync  执行数据同步

上述命令不需要手动执行,Redis 服务器会在建立好主从关系后,自动执行

从节点负责执行 psync 从主节点拉取数据

psync replicationid offset

replicationid 设为 ? ,offset 设为 -1,尝试进行全量复制

replicationid offset  设为具体值正整数,尝试进行增量复制

  主节点

从节点

1)replicationid  由主节点生成

主节点启动时会自动生成,从节点晋升成主节点时也会生成(即使同一个主节点,每次重启 replicationid 的值也不同)

从节点和主节点建立联系后,就会从主节点这边获取到 replicationid

当主节点和从节点通信时,如果发生网络波动,从节点可能认为主节点挂了

此时,从节点会成为主节点(自己生成一个 replicationid,同时保存之前的 replicationid为 replicationid2),后续网络稳定时,从节点可以根据 replicationid2 再连接 主节点

上述过程可以手动干预,也可以自动完成(哨兵机制)

2)offset  偏移量

主节点和从节点上都会维护 偏移量(整数)

主节点的偏移量 收到 修改操作 的命令占据的字节总和

从节点的偏移量  从节点从主节点同步的数据量

replicationid  offset  共同描述了一个“结果集合”

如果两台机器,replicationid 和 offset 一样,可以认为两台Redis机器上存储的数据完全一样

上述过程中,不是从节点索要那部分数据,主节点就给部分数据,主节点会自行判定

FULLRESYNC  全量数据的同步

CONTINUE  增量数据的同步

ERR  老版本的 Redis 服务器不支持 psync,可以使用 sync 替代

全量复制:

1.首次和主节点进行数据同步

2.主节点不方便进行部分复制

增量复制:

1.从节点已经从主节点上复制过数据,因为网络抖动重启或者从节点重启(此时大部分数据相似)

全量复制

1)从节点发送 psync 命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的运行 id 和 复制偏移量,所以发送 psync ?-1

2)主节点根据命令,解析出要进行全量复制,回复 +FULLRESYNC 响应

3)从节点接收到主节点的运行信息进行保存

4)主节点执行 bgsave 进行 rdb 文件的持久化

5)主节点发送 rdb 文件给从节点,从节点保存 rdb 数据到本地硬盘

6)主节点将从生成 rdb 到接收完成期间执行的命令,写入缓冲区,等从节点保存完 rdb 文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍按照 rdb 的二进制格式追加到收到的 rdb 文件中,保持主从一致性

7)从节点清空自身原有的旧数据

8)从节点加载 rdb 文件得到和主节点一样的数据

9)从节点加载 rdb 完成后,并且开启了 AOF 持久化功能,会进行 bgrewrite 操作,得到最近的 aof 文件

3)保存主节点 replid

4)不能使用已有的 rdb 文件,必须重新生成,已有的 rdb 文件可能会和当前最新的数据差异较大

5)从节点开启 AOF,在上述加载过程中,会产生大量的 aof 日志

针对 aof 日志进行必要的处理

无硬盘模式

主节点在进行全量复制时,也支持“无硬盘模式”(diskless)

主节点生成的 rdb 的二进制数据,不直接保存到文件中,直接在网络中传输

从节点之前是先收到二进制的 rdb 数据,写到硬盘,再加载,此时直接把收到的数据进行加载

(省下一系列写硬盘和读硬盘的操作,此处的 rdb 数据不是为了重启,同步数据)

即便引入“无硬盘模式”,整个操作仍然是比较重量的,网络传输是无法省略的

部分复制

从节点要从主节点这里进行全量复制(全量复制开销很大)

如果从节点已经持有主节点的绝大部分数据,此时就不需要全量复制

出现网络抖动,主节点修改的数据可能无法及时同步,当从节点已经感觉不到主节点时,从节点可能会升级成主节点

在从节点和主节点重新连接后,需要同步数据

psync  带有具体的 replid 和 offset 值,主节点只需要根据 psync 的参数判断即可

1)当主节点和从节点之间出现网络中断,超过 repl-timeout 时间,主节点会认为从节点故障,终端复制连接

2)从节点连接中断期间,主节点依然相应,这些命令因为网络中断无法及时发送给从节点,暂时保存在 复制积压缓冲区

3)主节点网络恢复时,从节点再次连上主节点

4)从节点将之前的保存的 replid 和 offset 作为 psync 的参数发送给主节点,请求进行部分复制

5)主节点接收到 psync 请求后,进行必要的验证。根据 offset 去 复制积压缓冲区 查找合适的数据,并响应 +CONTINUE 给从节点

6)主节点将需要从节点同步的数据发送给从节点,完成一致性

复制积压缓冲区

复制积压缓冲区 是保存在主节点上的一个固定长度的队列,默认大小为 1MB,当主节点有连接的从节点时被创建

当主节点响应写命令时,不仅会把命令发给从节点,还会写入 复制积压缓冲区

复制积压缓冲区 本质上是 先进先出的定长队列,能实现保存最近已经复制的数据的功能,用于部分复制和复制命令丢失的数据补救

replid 不同,进行全量复制

offset 超过积压缓冲区的范围,进行全量复制

实时复制

全量复制:从节点刚连上主节点,进行的数据初始化

部分复制:全量复制的特殊情况(优化手段,目的和全量复制相同)

实时复制:从节点和主节点已经同步数据,主节点获取的数据实时同步到从节点

从节点和主节点之间会建立 TCP的长连接

主节点将接收到的修改请求,通过上述连接,发给从节点,从节点根据请求修改数据

这个过程的延时时间比较短的,但遇到多层级的树状结构,延时会上升

在进行实时复制时,需要保证连接处于可用状态 —— 心跳包机制

主节点:默认每隔 10 s,给从节点发送 ping 命令,从节点收到就返回 pong

从节点:默认每隔 1 s,给主节点发起一个特定的请求,会上报当前从节点复制数据的进度  offset

runid 和 replid

一个 Redis 服务器上,replid 和 runid 都是存在的

1)runid 每个节点都不同  ——  标识一次 Redis 的“运行”

主要用于支持 Redis 哨兵机制,与主从复制无关

2)replid 具有主从关系的的节点是相同的  ——  主从复制

replid 和 offset 共同标识了一个数据集合

问题补充

从节点晋升成主节点

当主节点挂了,从节点虽然能提供读操作,但是从节点不能自动升级成主节点

此时,需要手动恢复节点 ——> Redis 哨兵,自动对挂了的主节点进行替换

主节点和从节点断开连接,有两种情况:

1)主节点主动和从节点断开连接  ——主动修改 Redis 的组成结构

slaveof no one 

此时,主节点自动晋升成主节点

2)主节点挂了

此时,从节点不会晋升成主节点,必须通过人工干预的方式恢复   ——> 高可用

Redis 主节点无法重启

当 Redis 重启时,需要加载 下面的文件:

从节点是通过手动启动的方式运行的,此时 root 用户下启动 Redis 服务器,于是生成的 aof 文件也就是 root 用户的文件

通过 service redis-server start 启动的 Redis 服务器,是通过一个 redis 这样的用户来启动的

redis server需要按照可读可写的方式打开这个 aof 文件,而这个文件对root之外的用户只有读权限

因此,server redis-server start  启动的 Redis 服务器无法打开 aof 文件,启动失败

在最开始创建从节点的配置文件中,三个 redis server 使用同一个 aof 文件

三个 redis server 里面的数据不一定一样

解决方案:把三个 Redis 服务器生成的文件区分开 ——> 直接把三个 Redis 服务器的 工作目录 区分开(修改配置文件中的 dir 选项)

1)停止之前的 Redis 服务器

2)删除之前工作目录下的已经生成 aof 文件 或者 通过 chown 命令修改 aof 文件所属的用户

3)给从节点创建出新的目录作为从节点的工作目录,并且修改从节点的配置文件,设定新的目录为工作目录

4)启动 Redis 服务器

http://www.xdnf.cn/news/1471.html

相关文章:

  • Codeforces Round 998 (Div. 3) ABCD
  • 深度解析 Java 中的 `computeIfAbsent`:原理、最佳实践与高级用法
  • Leetcode98、230:二叉搜索树——递归学习
  • 第12章:MCP服务端项目开发实战:数据持久化
  • React Ref引用机制解析
  • 文档构建:Sphinx全面使用指南 — 进阶篇
  • Axure中继器表格:实现复杂交互设计的利器
  • Linux磁盘管理
  • QT项目----电子相册(4)
  • 单片机通讯外设 (UART)、I2C、SPI、CAN 和 LIN 时序分析 使用场景以及优缺点对比分析报告
  • stm32之GPIO函数详解和上机实验
  • Spring Boot中的监视器:Actuator的原理、功能与应用
  • 基于PySide6与CATIA的直齿圆柱齿轮参数化建模系统开发实践
  • 湖南大学-操作系统实验四
  • 将天气查询API封装为MCP服务
  • godot源码编译
  • 【AI News | 20250423】每日AI进展
  • 数据库-基本概述 和 SQL 语言
  • SQL进阶知识:五、存储过程和函数
  • JAVA并发根源问题的讨论与思考
  • 2024沈阳区域赛,D - Dot Product Game
  • Visual Studio2022 配置 SDL3及拓展库
  • 从一个简单的HelloWorld来完整介绍Java的类加载过程
  • Python——流程控制
  • 代码分享:python实现svg图片转换为png和gif
  • linux软硬连接
  • 3.1 Agent定义与分类:自主Agent、协作Agent与混合Agent的特点
  • Vue3祖先后代组件数据双向同步实现方法
  • 基于STM32、HAL库的MAX5402EUA数字电位器驱动程序设计
  • Qt creator 16.0.1 语言家失效解决方法