Redis Sentinel 深度解析:构建高可用性 Redis 集群

2024-09-07 17:12

本文主要是介绍Redis Sentinel 深度解析:构建高可用性 Redis 集群,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Redis Sentinel 深度解析:构建高可用性 Redis 集群

  • 一 . 基本概念
    • 1.1 相关名词解释
    • 1.2 如何人工恢复主节点故障 ?
    • 1.3 哨兵自动恢复主节点故障
  • 二 . 哨兵的安装部署
    • 2.1 安装 docker 和 docker-compose
    • 2.2 搭建 Redis 的哨兵环境
      • 2.2.1 编排 Redis 的主从节点
      • 2.2.2 编排 redis-sentinel 节点
      • 2.2.3 启动容器
  • 三 . 哨兵节点的演示
    • 3.1 模拟主节点下线
    • 3.2 主从切换的具体流程
  • 四 . 小结

Hello , 大家好 , 这个专栏给大家带来的是 Redis 系列 ! 本篇文章给大家讲解的是 Redis 的集群. Redis 集群是一种提供自动分区的 Redis 数据库实现,它将数据自动分配到多个节点上。每个节点负责整个键值空间的一部分,从而允许数据库的扩展超越单个机器的内存限制。Redis 集群通过使用分片(sharding)技术来实现数据的分布式存储,同时提供一定程度的高可用性和容错能力。

在这里插入图片描述
本专栏旨在为初学者提供一个全面的 Redis 学习路径,从基础概念到实际应用,帮助读者快速掌握 Redis 的使用和管理技巧。通过本专栏的学习,能够构建坚实的 Redis 知识基础,并能够在实际学习以及工作中灵活运用 Redis 解决问题 .
专栏地址 : Redis 入门实践

一 . 基本概念

在 Redis 的主从复制中 , 存在一个关键的问题 : 如果主节点挂了 , 那整个系统读操作是可以继续进行的 , 但是写操作是执行不了的 . 那我们要想恢复这种情况 , 就需要人工来去进行维修 , 或者人工进行配置让其中一个从节点晋升为主节点 .

那能否通过自动化的手段来去解决主节点挂了的问题呢 ?

在 Redis 2.8 之后就提供了哨兵机制 (Sentinel) 来解决这个问题 .

1.1 相关名词解释

名词逻辑结构物理结构
主节点Redis 主服务一个独立的 redis-server 进程
从节点Redis 从服务一个独立的 redis-server 进程
Redis 数据节点主从节点主节点和从节点的进程
哨兵节点监控 Redis 数据节点的节点一个独立的 redis-sentinel 进程
哨兵节点集合若干哨兵节点的抽象组合若干 redis-sentinel 进程
Redis 哨兵 (sentinel)Redis 提供的高可用方案哨兵节点集合和 Redis 主从集合
应用方访问 Redis 的客户端一个或多个连接 Redis 的进程

哨兵机制 , 是通过独立的进程来体现的 , 和之前学习的 redis-server 是不同的进程 , 哨兵节点不负责存储数据 , 只是对其他的 redis-server 进程起到监控的效果 .

在实际情况下 , 哨兵节点也是一组集合 (多个哨兵节点构成) , 防止单个哨兵节点挂了影响到整个系统的监控 .

1.2 如何人工恢复主节点故障 ?

1.3 哨兵自动恢复主节点故障

那 Redis 哨兵核心的功能就有这几点 :

  1. 监控 : 监控主节点和从节点的工作状态 , 并且能及时发现某个节点是否挂了
  2. 自动故障转移 : 如果主节点挂了 , 那哨兵就会自动选出一个新的从节点升级为主节点 , 保证整体依然可以进行读和写
  3. 通知 : 转移结束之后 , 就会通知客户端新的主节点

一般来说 , Redis 哨兵节点也是多个一起工作的 , 只有一个哨兵节点工作其实也是可以的 , 但是并不推荐

  1. 如果哨兵节点只有一个 , 他自身也是非常容易出现问题的 . 万一这个哨兵节点挂了 , 后续 Redis 节点挂了那就没有办法自动进行恢复了
  2. 出现误判的概率也比较高 : 网络传输非常容易出现抖动 / 延迟 / 丢包 , 一般来说都是短时间的异常 , 那如果只有一个哨兵节点 , 他就会认为该节点出现了问题 , 导致很容易出现误判 .

在分布式系统中 , 应该避免使用各种 “单点” , 也就是一定要多堆料 .

二 . 哨兵的安装部署

我们准备搭建出这样的结构

按理说 , 这六个节点 , 是需要部署在六个不同的服务器主机上的

那我们只有一个云服务器 , 就只能在一个云服务器上 , 完成这里的环境搭建 .

在实际工作中 , 把上述节点都放到一个服务器上 , 是没有任何意义的 .

由于这些节点比较多 , 相互之间容易产生冲突 . 如果直接部署 , 就需要手动修改很多配置 , 来去分别设置不同的端口号、不同的配置文件、不同的工作目录等 . 这种方式比较繁琐 , 也会和在不同主机上部署存在很大的差异 .

利用 docker 就可以有效的解决上述麻烦的问题 , docker 就相当于一个虚拟机 , 通过软件就可以在一台电脑上模拟出另外的一些硬件资源 (就相当于构造了另外一个虚拟的电脑) , 虚拟机他最大的问题就是比较吃配置 . 这个事情对于我们的云服务器来说压力非常大 .

相比之下 , docker 就能够解决这样的问题 , docker 就相当于一个轻量虚拟机 , 不仅起到了虚拟机这样的隔离环境的效果 , 也没有消耗很多的硬件资源 .

2.1 安装 docker 和 docker-compose

Docker 中的一个重要的概念 , 叫做容器 , 容器就可以看做是一个轻量级的虚拟机 .

那 docker-compose 的作用就是便于管理一系列的容器

后续我们会将安装 Docker 和 docker-compose 的方法补充到这里

2.2 搭建 Redis 的哨兵环境

我们使用 docker-compose 来进行容器的编排工作

容器的编排指的是我们目前涉及到多个 Redis server , 也有多个 Redis 哨兵节点 . 每一个 Redis server / 每一个哨兵节点都是作为一个单独的容器 .

那我们总共需要 6 个容器 , 每个容器单独配置也是比较麻烦的 , 所以我们需要 docker-compose 来帮助我们进行容器编排

利用 docker-compose 的方式 , 通过一个配置文件 , 把具体要创建哪些容器以及每个容器运行的各种参数描述清楚 , 后续通过一个简单的命令就能够批量的启动 / 停止这些容器了 .

docker-compose 使用 yml 这样的格式来去作为配置文件 .

那接下来我们就开始部署一下 docker-compose , 我们的需求是

  • 创建三个容器 , 作为 Redis 的数据节点 (一主二从)
  • 创建三个容器 , 作为 Redis 的哨兵节点

那我们分别创建各自的 yml 文件来去配置

其实也可以用一个 yml 文件直接启动 6 个容器 , 但是如果这 6 个容器同时启动 , 就有可能出现这种情况 :

如果哨兵节点先启动完成 , 数据节点后启动完成 , 那哨兵节点就会认为是数据节点挂了 , 导致一些日志打印不符合我们的预期

2.2.1 编排 Redis 的主从节点

首先 , 我们先创建一个 redis 目录 , 然后进入该目录

mkdir redis
cd redis

然后创建两个文件夹

  • redis-data : 存放数据节点
  • redis-sentinel : 存放哨兵节点
mkdir redis-data
mkdir redis-sentinel

然后进入到 redis-data 目录中 , 用 vim 编辑器去编辑 docker-compose.yml 这个文件

cd redis-data
vim docker-compose.yml

然后将这段配置粘贴到配置文件中

version: '3.7'
services:master:image: 'redis:5.0.9'container_name: redis-masterrestart: alwayscommand: redis-server --appendonly yesports:- 6379:6379slave1:image: 'redis:5.0.9'container_name: redis-slave1restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6380:6379slave2:image: 'redis:5.0.9'container_name: redis-slave2restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6381:6379

我们也来看一下这个配置文件的含义

此时我们就可以启动该配置了 , 使用 docker-compose up -d 命令

那我们还可以通过 netstat -anp | grep 6379 … 6380 … 6381 就可以查看一下端口是否被占用 , 如果被占用就代表容器已经启动

接下来我们可以启动一下客户端 , 使用 redis-cli -p 6379 命令 , 就连接到了容器当中的 Redis 了

我们还可以通过 docker-compose logs 来去查看这些容器产生的日志

2.2.2 编排 redis-sentinel 节点

我们进入到 redis-sentinel 目录 , 然后用 vim 打开 docker-compose.yml 文件

cd /root/redis/redis-sentinel
vim docker-compose.yml

然后将该配置文件粘贴进去

version: '3.7'
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379sentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379sentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379

我们还是来看一下 redis-sentinel 配置文件的含义

那我们还需要创建出 sentinel1、sentinel2、sentinel3 这三个配置文件 . 初始情况下 , 这三个配置内容文件可以相同 , 当容器启动之后就会对配置文件进行自适应调整 . 下面就是 sentinel.conf 配置文件的内容

bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000

那接下来我们就需要在 /root/redis/redis-sentinel 路径下创建出 sentinel1、sentinel2、sentinel3 这三个配置文件

cd /root/redis/redis-sentinel
vim sentinel1.conf
cp sentinel1.conf sentinel2.conf
cp sentinel1.conf sentinel3.conf

2.2.3 启动容器

使用命令 docker-compose up -d 命令按照后台进程的方式启动 , 稍等片刻之后三个哨兵节点就已经启动

-d 参数指的就是按照后台进程的方式来启动

然后我们通过 docker-compose logs 命令来去查看启动日志

我们发现日志中有一些错误 , 他的意思是我们的配置文件中有错误 , 在第三行位置

也就是说 , 哨兵节点不认识 redis-master . redis-master 此处就相当于一个域名 , Docker 就会自动进行域名解析 , 但是现在解析失败了 .

失败的原因主要是 docker-compose 一下子启动了 N 个容器 , 此时这 N 个容器都处于同一个局域网中 , 那这 N 个局域网就可以进行互相访问 . 但是我们目前三个 redis-server 节点是在一个局域网 , 三个哨兵节点是在另一个局域网 , 默认情况下不同局域网之间是不互通的 .

解决方案就是将这两次不同的 docker-compose 操作对应的容器放到同一个局域网中 , 使用 docker network ls 列出当前 docker 中的局域网 , 然后根据列出来的数据再去进行下一步的配置

我们先启动了三个 redis-server 节点 , 就相当于自动创建了第一个局域网 . 然后再启动三个哨兵节点 , 就又创建了第二个局域网 .

我们要做的是之后再去执行 docker-compose 命令的时候 , 不自动创建新的局域网 , 直接加入到已有的局域网 .

解决的方法就是在我们 redis-sentinel 节点的配置文件中 , 在最后面添加 network 配置

version: '3.7'
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379sentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379sentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379
networks:default:external:name: redis-data_default

我们重新打开 redis-sentinel 文件夹下的配置文件进行粘贴

cd /root/redis/redis-sentinel
vim docker-compose.yml

然后配置完毕就可以重新启动容器了 , 先使用 docker-compose down 命令停止掉当前 docker 服务 , 然后重新执行 docker-compose up -d 命令

然后我们重新来看一下启动日志 , 使用 docker-compose logs 命令 , 此时日志也就正常打印了

三 . 哨兵节点的演示

哨兵节点存在的意义就是能够在 Redis 主从结构出现问题的时候 (比如 : 主节点挂了) , 此时哨兵节点就能够自动的帮我们重新选举出一个新的节点来去代替之前的主节点 , 保证整个 Redis 是可用状态 .

我们可以先看一下目前存在的节点信息 , 使用 docker ps -a 命令

接下来 , 我们就可以模拟一下主节点挂了的情况

3.1 模拟主节点下线

我们使用 docker stop 容器名称来去停止主节点

当我们主节点挂了的时候 , 哨兵节点此时就已经开始工作了 , 我们可以观察一下哨兵节点的日志

cd /root/redis/redis-sentinel
docker-compose logs

我们重点观察一个哨兵节点的日志 , 我们选择 redis-sentinel-3 这个哨兵节点

此时 , 主节点已经恢复 , 我们尝试连接一下 Redis 客户端

那 6379 服务已经下线 , 6380 升级成了新的主节点 , 那 6381 应该就是从节点 , 只不过父节点变成了 6380

那此时 , 如果我们将下线的主节点重新启动 , 会发生什么 ?

使用命令 docker start redis-master 命令

我们可以看到 , 之前的主节点虽然正常启动了 , 但是他的身份从主节点变成了从节点 , 挂在了新的主节点的下面

3.2 主从切换的具体流程

哨兵节点重新选取主节点的流程

四 . 小结

  1. 哨兵节点不能只有一个 , 否则单个哨兵节点挂了就会影响系统的可用性 .
  2. 哨兵节点最好是奇数个 , 方便选举 leader , 得票更容易超过半数 .
  3. 哨兵节点不负责存储数据 , 只负责监控主从节点 , 真正存储和读取数据的是 Redis 的主从节点 , 因此哨兵节点就可以使用一些配置不高的机器来部署 .
  4. “哨兵+主从复制” 解决的问题是提高可用性 , 并不能解决数据极端情况下写丢失的问题 .
  5. “哨兵+主从复制” 并不能提高数据的存储容量 . 使用 Redis 中的集群 , 就是解决存储容量问题的有效方案 , 敬请期待 .

对于 Redis 中的哨兵机制 , 我们就分享到这里 , 如果对你有帮助的话 , 请一键三连 , 谢谢~
在这里插入图片描述

这篇关于Redis Sentinel 深度解析:构建高可用性 Redis 集群的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145650

相关文章

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Springboot 中使用Sentinel的详细步骤

《Springboot中使用Sentinel的详细步骤》文章介绍了如何在SpringBoot中使用Sentinel进行限流和熔断降级,首先添加依赖,配置Sentinel控制台地址,定义受保护的资源,... 目录步骤 1: 添加 Sentinel 依赖步骤 2: 配置 Sentinel步骤 3: 定义受保护的

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Redis存储的列表分页和检索的实现方法

《Redis存储的列表分页和检索的实现方法》在Redis中,列表(List)是一种有序的数据结构,通常用于存储一系列元素,由于列表是有序的,可以通过索引来访问元素,因此可以很方便地实现分页和检索功能,... 目录一、Redis 列表的基本操作二、分页实现三、检索实现3.1 方法 1:客户端过滤3.2 方法

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增