Redis(八):Redis高并发高可用(哨兵Sentinel)

在构建高并发系统时,Redis 的高可用性成为了核心基础设施的一部分。本文将带你深入理解 Redis Sentinel 的工作机制与配置方法,帮助你构建一个具备容错能力的 Redis 集群。

主从复制的问题

Redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用场景这种故障处理的方式是无法接受的。

  • 主节点单点故障:主节点挂了,系统写不可用,需要手动干预切换主从
  • 故障转移不自动:必须人工介入,延迟恢复

哨兵Sentinel

Redis 从 2.8 开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。

Redis Sentinel 是 Redis 官方提供的高可用解决方案,具备以下核心功能:

  • 故障检测:监控 Redis 主从实例的运行状态。
  • 通知机制:当实例状态变更时通知管理员或其他系统。
  • 自动故障转移:当主节点不可用时,自动将从节点升级为主节点。
  • 服务发现:客户端可以通过 Sentinel 获取最新的主节点地址。

Sentinel 自身是一个特殊的 Redis 实例(运行在不同端口上,通常是 26379)。多个 Sentinel 可以组成哨兵集群,它们之间通过类似 Gossip 协议进行通信。

核心流程:

  1. Sentinel 节点周期性 Ping 主从节点。
  2. 当一个 Sentinel 判断主节点不可达时,标记为主观下线(SDOWN)
  3. 多个 Sentinel 达成一致后,认为主节点客观下线(ODOWN)
  4. 发起故障转移(failover),选举一个从节点为新主节点。
  5. 其余从节点重新指向新主节点。
哨兵配置文件

已知条件,哨兵节点每间隔1s 向主从节点发送一次ping。

三个哨兵均指向主节点(6379),具体配置如下:

选举

sentinel1.conf

bash 复制代码
# sentinel monitor <name> <ip> <port> <quorum>
# quorum 表示"多少个哨兵主观判断主节点故障,才算客观下线(ODOWN)

port 26379
sentinel monitor mymaster 172.17.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1

sentinel2.conf

bash 复制代码
port 26380
sentinel monitor mymaster 172.17.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1

sentinel3.conf

bash 复制代码
port 26381
sentinel monitor mymaster 172.17.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1

启动三个哨兵节点,如下图示:

bash 复制代码
docker run -d --name redis-sentinel1 -p 26379:26379 -v E:\CK\learn\docker\redis\sentinel1.conf:/etc/sentinel.conf redis:7.2.4 redis-sentinel /etc/sentinel.conf

docker run -d --name redis-sentinel2 -p 26380:26380 -v E:\CK\learn\docker\redis\sentinel2.conf:/etc/sentinel.conf redis:7.2.4 redis-sentinel /etc/sentinel.conf

docker run -d --name redis-sentinel3 -p 26381:26381 -v E:\CK\learn\docker\redis\sentinel3.conf:/etc/sentinel.conf redis:7.2.4 redis-sentinel /etc/sentinel.conf
bash 复制代码
# 主节点
C:\Users\86158>docker exec -it redis-master redis-cli
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> set k2 v2
OK

# 从节点6380
C:\Users\86158>docker exec -it myredis2 redis-cli -p 6380
127.0.0.1:6380> slaveof 192.168.10.9 6379
OK
127.0.0.1:6380> keys *
1) "k1"
127.0.0.1:6380> keys *
1) "k1"
2) "k2"

# 从节点6381
C:\Users\86158>docker exec -it myredis3 redis-cli -p 6381
127.0.0.1:6381> slaveof 192.168.10.9 6379
OK
127.0.0.1:6381> keys *
1) "k1"
127.0.0.1:6381> keys *
1) "k1"
2) "k2"

通过同步主节点的数据可以明确了目前的架构为:一主(6379)二子(63806381)。

此时,我们让主节点宕机

bash 复制代码
docker stop redis-master

以哨兵3节点为例,查看主节点宕机后,哨兵节点的选举过程,如下图:

  1. Subjectively Down(SDOWN)
    • 当前 Sentinel 自己主观地认为 主节点 mymaster(即 192.168.10.9:6379)不可用了
    • 这个判断是"本哨兵自己觉得",是单方面的判断
  2. Objectively Down(ODOWN)
    • 表示已经达到法定票数(quorum),多个 Sentinel 一致认为主节点真的挂了
    • quorum 2/2 表示:当前已有 2 个哨兵都同意主节点宕机,而 Sentinel 配置中设置的 quorum 是 2(注意,哨兵1和2,此处是3/2,应该是某些不可抗力因素导致)
  3. 哨兵进入了一个新的故障转移纪元epoch),编号为 1
    • 每次进行主节点切换时,都会开始一个新的 epoch,用于区分多次 failover 过程;
    • 每个 Sentinel 会在其内部状态中记录当前 epoch;
    • epoch 是分布式系统中常用的"版本"概念,避免重复选主等问题。
  4. 哨兵发起一次尝试性的 选举流程(failover),准备开始主从切换流程
  5. ...(投票过程)
  6. 哨兵节点更新自己的配置文件(依据选举的主节点信息)
  7. 哨兵正式宣布7380为主节点
  8. 6381配置为6380的从节点
  9. 6379配置为6380的从节点

此时查看 6380 已经是主节点

bash 复制代码
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.17.0.6,port=6381,state=online,offset=1462404,lag=1
master_failover_state:no-failover
master_replid:2f0e1a4b37532e11dd11f64526f1e6572f765bfe
master_replid2:3d2c88cb06af1e654fd2ca4631f68536ebbdd625
master_repl_offset:1462539
second_repl_offset:342873
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:404070
repl_backlog_histlen:1058470

此时查看 6381,其依然为从节点,但是其主节点已变为6380

bash 复制代码
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:172.17.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:1480350
slave_repl_offset:1480350
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:2f0e1a4b37532e11dd11f64526f1e6572f765bfe
master_replid2:3d2c88cb06af1e654fd2ca4631f68536ebbdd625
master_repl_offset:1480350
second_repl_offset:342873
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:421582
repl_backlog_histlen:1058769
yaml 复制代码
6379(旧主) ─┐  → 掉线
              │
Sentinel 投票 → 6380(新主)
              │
           ┌──┴────────┐
           ↓           ↓
        6381        6379
      (原副本)   (变 slave)
         ↑
    172.17.0.6:6381 也加入从节点

6379 又挂了,+sdown slave

哨兵Sentinel的优缺点

✅ 优点(相比主从):

  • 自动故障转移:主节点宕机后,哨兵自动选举一个从节点为新的主节点。
  • 高可用支持:支持对主从架构的监控、通知、故障恢复。
  • 运维成本低:比纯主从更自动化,降低人为干预。

❌ 弊端:

  • 写仍是单点瓶颈:无论主节点自动切换多少次,写能力仍受限于单个主节点。
  • 扩展性不足:不能横向扩展写能力,数据量过大时,主节点内存也会成为瓶颈。
  • 数据分片不支持:所有节点都保存完整数据副本,浪费内存资源,无法水平扩展。

由以上哨兵模式的缺点,下一节将引入集群模式,敬请期待。

相关推荐
Pitayafruit3 小时前
【📕分布式锁通关指南 12】源码剖析redisson如何利用Redis数据结构实现Semaphore和CountDownLatch
redis·分布式·后端
Code季风5 小时前
分布式系统中的幂等性设计:从理论到实现的全面指南
redis·分布式·微服务
Badman5 小时前
Redis与DB的数据一致性问题梳理
数据库·redis·后端
weixin_3077791312 小时前
Redis Windows迁移方案与测试
c++·windows·redis·算法·系统架构
yh云想16 小时前
《RedisTemplate 核心操作全解析》
redis·spring·redistemplate
vision_wei_16 小时前
Redis中间件(二):Redis协议与异步方式
网络·数据库·c++·redis·分布式·缓存·中间件
代码的余温16 小时前
Redis内存耗尽时的应对策略
数据库·redis·缓存
爱学习的小熊猫_18 小时前
在Linux上部署RabbitMQ、Redis、ElasticSearch
linux·redis·elasticsearch·中间件·rabbitmq
平生不喜凡桃李19 小时前
Linux 线程同步与互斥
java·jvm·redis