redis - 哨兵

Redis 的主从复制模式下,⼀旦主节点由于故障不能提供服务,需要人工进行主从切换,同时大量 的客户端需要被通知切换到新的主节点上,对于上了⼀定规模的应⽤来说,这种⽅案是⽆法接受的, 于是 Redis 从 2.8 开始提供了 Redis Sentinel(哨兵)来自动化解决这个问题。

由于对 Redis 的许多概念都有不同的名词解释,所以在介绍 Redis Sentinel 之前,先对⼏个名词 概念进⾏必要的说明,如表所⽰。

|--------------------|------------------|-------------------------|
| 名词 | 逻辑结构 | 物理结构 |
| 主节点 | Redis 主服务 | ⼀个独⽴的 redis-server 进程 |
| 从节点 | Redis 从服务 | ⼀个独⽴的 redis-server 进程 |
| Redis 数据节点 | 主从节点 | 主节点和从节点的进程 |
| 哨兵节点 | 监控 Redis 数据节点的节点 | ⼀个独⽴的 redis-sentinel 进程 |
| 哨兵节点集合 | 若⼲哨兵节点的抽象组合 | 若⼲ redis-sentinel 进程 |
| Redis 哨兵(Sentinel) | Redis 提供的高可用方案 | 哨兵节点集合 和 Redis 主从节点 |
| 应⽤⽅ | 泛指⼀个多多个客⼾端 | ⼀个或多个连接 Redis 的进程 |

哨兵机制,是通过独立的 进程 来体现的。和之前 redis-server 是不同的进程!

redis-sentinel 不负责存储数据,只是对其他的 redis-server 进程起到监控的效果~~

通常哨兵节点,也会搞一个集合~~ (多个哨兵节点构成的),防止单个哨兵节点

主从复制的问题

Redis 的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作⽤: 第⼀,作为主节点的⼀个备份,⼀旦主节点出了故障不可达的情况,从节点可以作为后备 "顶" 上 来,并且保证数据尽量不丢失(主从复制表现为最终⼀致性)。第⼆,从节点可以分担主节点上的读 压⼒,让主节点只承担写请求的处理,将所有的读请求负载均衡到各个从节点上。 但是主从复制模式并不是万能的,它同样遗留下以下⼏个问题:

  1. 主节点发生故障时,进行主从切换的过程是复杂的,需要完全的人工参与,导致故障恢复时间⽆法 保障。

  2. 主节点可以将读压⼒分散出去,但写压⼒/存储压⼒是⽆法被分担的,还是受到单机的限制。 其中第⼀个问题是高可用问题,即 Redis 哨兵主要解决的问题。第⼆个问题是属于存储分布式的问 题,留给 Redis 集群去解决。

人工操作

Redis 主节点故障后需要进⾏的人工操作

1)运维⼈员通过监控系统,发现 Redis 主节点故障宕机。

2)运维⼈员从所有节点中,选择⼀个(此处选择了 slave 1)执行 slaveof no one,使其作为新的主 节点。

3)运维⼈员让剩余从节点(此处为 slave 2)执行 slaveof {newMasterIp} {newMasterPort} 从新主节 点开始数据同步。

4)更新应用方连接的主节点信息到 {newMasterIp} {newMasterPort}。

5)如果原来的主节点恢复,执行 slaveof {newMasterIp} {newMasterPort} 让其成为⼀个从节点。

这样的人工干预,还是比较繁琐的。

其次,人工干预的过程出现操作不当,数据丢失,也是很严重的。

还有人工干预也需要时间消耗。

哨兵自动恢复主节点故障

当主节点出现故障时,Redis Sentinel 能⾃动完成故障发现和故障转移,并通知应⽤⽅,从⽽实现 真正的⾼可⽤。

Redis Sentinel 是⼀个分布式架构,其中包含若⼲个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进⾏监控,当它发现节点不可达时,会对节点做下线表⽰。如果下线的是主节点,它还会和其他的 Sentinel 节点进⾏ "协商",当⼤多数 Sentinel 节点对 主节点不可达这个结论达成共识之后,它们会在内部 "选举" 出⼀个领导节点来完成⾃动故障转移的 ⼯作,同时将这个变化实时通知给 Redis 应用方。整个过程是完全⾃动的,不需要⼈⼯介⼊。整体的 架构如图所示。

监控:这些进程之间,会建立tcp长连接,通过这样的长连接,定期发送心跳包。

Redis Sentinel 相⽐于主从复制模式是多了若干(建议保持奇数)Sentinel 节点⽤于实现监控数据节 点,哨兵节点会定期监控所有节点(包含数据节点和其他哨兵节点)。针对主节点故障的情况,故障 转移流程⼤致如下:

1)主节点故障,从节点同步连接中断,主从复制停⽌。

2)哨兵节点通过定期监控发现主节点出现故障。哨兵节点与其他哨兵节点进行协商 ,达成多数认同主 节点故障的共识。这步主要是防⽌该情况:出故障的不是主节点,⽽是发现故障的哨兵节点,该情况 经常发生于哨兵节点的网络被孤⽴的场景下。

3)哨兵节点之间使⽤ Raft 算法选举出⼀个领导角色,由该节点负责后续的故障转移⼯作。

4)哨兵领导者开始执⾏故障转移:从节点中选择⼀个作为新主节点,执行 slaveof no one;让其他从节点同步新主节点,修改 slaveof 到新的主节点上;通 知应用层转移到新主节点。

通过上⾯的介绍,可以看出 Redis Sentinel 具有以下几个功能:

• 监控: Sentinel 节点会定期检测 Redis 数据节点、其余哨兵节点是否可达。

• 故障转移: 实现从节点晋升(promotion)为主节点并维护后续正确的主从关系。

• 通知: Sentinel 节点会将故障转移的结果通知给应用方。

注意, redis 哨兵节点,有一个,也是可以的。但是,1、如果哨兵节点只有一个,它自身也是容易出现问题的,万一这个哨兵节点挂了,后续redis节点也挂了,就无法进行自动的恢复过程了。2、出现误判的概率也比较高,毕竟网络传数据是容易出现抖动或者延迟或者丢包的,如果只有一个哨兵节点,出现上述问题之后,影响就比较大。

因此在分布式系统中,应该避免使用"单点",哨兵节点,最好要设置奇数个(方便后续的选举),最少也应该是3个。

安装部署

目前搭建的拓扑如下

但是目前我只有一台云服务器,所以使用docker虚拟化来模拟这样的拓扑结构。

1、拉取redis镜像,执行命令 docker pull redis:5.0.9

准备好如下目录

2、在redis-data目录下编写docker-compose.yml文件编排redis主从节点

bash 复制代码
#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:
      - 8081:6379
  slave2:
    image: 'redis:5.0.9'
    container_name: redis-slave2
    restart: always
    command: redis-server --appendonly yes --slaveof redis-master 6379
    ports:
      - 8082:6379

在执行命令创建容器 docker compose up -d

在查看(docker ps -a | grep redis), 容器就启起来了

3、在rredis-sentinel目录下编写docker-compose.yml文件编排哨兵节点

bash 复制代码
#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:
      - 8083: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:
      - 8084: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:
      - 8085:26379
networks:
  default:
    name: redis-data_default
    external: true

然后在当前目录下新建sentinel1.conf、sentinel2.conf、sentinel3.conf配置文件

首先编写sentinel1.conf文件

sentinel2.conf和sentinel3.conf类似配置,初始情况,这三个文件可以是一样的,随着运行哨兵节点会自适应调整配置的内容。

然后启动容器,执行命令 docker compose up -d

然后再查看容器

目前,redis主从节点和哨兵节点就部署好了

然后再次查看sentinel1.conf文件,发现配置文件就不一样了,这就是哨兵的配置重写

哨兵节点的作用演示

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

目前redis主从节点和哨兵节点都是正常运行的。

模拟主节点挂了的情况,将redis-master停掉,执行命令 docker stop redis-master

然后查看日志,执行命令 docker compose logs

然后登录8081从节点,观察是否调整为主节点

然后登录8081从节点,观察

主从切换的具体流程

1.主观下线

哨兵节点通过心跳包,判定 redis 服务器是否正常工作.如果心跳包没有如约而至,就说明 redis 服务器挂了。
此时还不能排除网络波动的影响,因此就只能是单方面认为这个redis 节点挂了

2.客观下线
多个哨兵都认为主节点挂了,(认为挂了的哨兵节点数目达到法定票数)哨兵们就认为这个主节点是客观下线.

3.要让多个哨兵节点,选出一个 leader 节点(多个哨兵节点投票选举一个哨兵节点出来)
由这个leader负责选一个从节点作为新的主节点,这个投票过程,主要看谁的网络时延小。

  1. 此时leader 选举完毕,leader 就需要挑选一个从节点,作为新的主节点。
  1. 优先级 每个 redis 数据节点,都会在配置文件中,有一个优先级的设置。 slave-priority
    优先级高的从节点,就会胜出。(当没有修改,使用默认优先级,就是大家都是一样的)

  2. offset 最大, 就胜出。offset表示从节点从主节点这边同步数据的进度。数值越大,说明从节点的数据和主节点就越接近。

  3. run id 是在每个 redis 节点启动的时候随机生成的一串数字,此时选谁都行,全凭缘分了。

把新的主节点指定好了之后,leader 就会控制这个这个节点,执行 slave no one ,成为 master,
再控制其他节点,执行 slave of,让这些其他节点,以新的 master 作为主节点了。

注意事项:

• 哨兵节点不能只有⼀个, 否则哨兵节点挂了也会影响系统可⽤性。

• 哨兵节点最好是奇数个, ⽅便选举 leader, 得票更容易超过半数。

• 哨兵节点不负责存储数据, 仍然是 redis 主从节点负责存储。所以哨兵节点可以使用一些配置不高的机器来部署(实际场景下,不能部署在一台机器上)。

• 哨兵 + 主从复制解决的问题是 "提高可用性", 不能解决 "数据极端情况下写丢失" 的问题。

• 哨兵 + 主从复制不能提⾼数据的存储容量, 当我们需要存的数据接近或者超过机器的物理内存, 这样 的结构就难以胜任了。

为了能存储更多的数据, 就引⼊了集群

相关推荐
岙利岙几秒前
MySQL使用jemalloc作为内存分配器
数据库·mysql·jemalloc
大G的笔记本3 分钟前
redis相关概念解释
redis
老年DBA6 分钟前
PostgreSQL BRIN索引揭秘
数据库·postgresql
小光学长10 分钟前
基于微信小程序的评奖评优系统51r12nd0(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·微信小程序·小程序
煎蛋学姐14 分钟前
SSM校园扶助综合服务平台的设计与实现r941j(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·校园扶助平台
ℳ₯㎕ddzོꦿ࿐15 分钟前
企业级 MySQL 8.0 物理备份实践:使用 XtraBackup 实现全量与增量自动备份
数据库·mysql
羊小猪~~20 分钟前
数据库学习笔记(十八)--事务
数据库·笔记·后端·sql·学习·mysql
零度@30 分钟前
Java-Redis 缓存「从入门到黑科技」2026 版
java·redis·缓存
optimistic_chen32 分钟前
【Redis 系列】常用数据结构---ZSET类型
数据结构·数据库·redis·xshell·zset·redis命令
cike_y34 分钟前
Spring整合Mybatis:dao层
java·开发语言·数据库·spring·mybatis