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

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-master
    restart: always
    command: redis-server --appendonly yes
    ports:
      - 6379:6379
  slave1:
    image: 'redis:5.0.9'
    container_name: redis-slave1
    restart: always
    command: redis-server --appendonly yes --slaveof redis-master 6379
    ports:
      - 6380:6379
  slave2:
    image: 'redis:5.0.9'
    container_name: redis-slave2
    restart: always
    command: redis-server --appendonly yes --slaveof redis-master 6379
    ports:
      - 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-1
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel1.conf:/etc/redis/sentinel.conf
    ports:
      - 26379:26379
  sentinel2:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-2
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/etc/redis/sentinel.conf
    ports:
      - 26380:26379
  sentinel3:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-3
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/etc/redis/sentinel.conf
    ports:
      - 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-1
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel1.conf:/etc/redis/sentinel.conf
    ports:
      - 26379:26379
  sentinel2:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-2
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/etc/redis/sentinel.conf
    ports:
      - 26380:26379
  sentinel3:
    image: 'redis:5.0.9'
    container_name: redis-sentinel-3
    restart: always
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/etc/redis/sentinel.conf
    ports:
      - 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 中的哨兵机制 , 我们就分享到这里 , 如果对你有帮助的话 , 请一键三连 , 谢谢~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加勒比海涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值