Redis(八):Redis高并发高可用(哨兵Sentinel)
在构建高并发系统时,Redis 的高可用性成为了核心基础设施的一部分。本文将带你深入理解 Redis Sentinel 的工作机制与配置方法,帮助你构建一个具备容错能力的 Redis 集群。
主从复制的问题
Redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用场景这种故障处理的方式是无法接受的。
- 主节点单点故障:主节点挂了,系统写不可用,需要手动干预切换主从
- 故障转移不自动:必须人工介入,延迟恢复
哨兵Sentinel
Redis 从 2.8
开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。
Redis Sentinel 是 Redis 官方提供的高可用解决方案,具备以下核心功能:
- 故障检测:监控 Redis 主从实例的运行状态。
- 通知机制:当实例状态变更时通知管理员或其他系统。
- 自动故障转移:当主节点不可用时,自动将从节点升级为主节点。
- 服务发现:客户端可以通过 Sentinel 获取最新的主节点地址。
Sentinel 自身是一个特殊的 Redis 实例(运行在不同端口上,通常是 26379
)。多个 Sentinel 可以组成哨兵集群,它们之间通过类似 Gossip 协议进行通信。
核心流程:
- Sentinel 节点周期性 Ping 主从节点。
- 当一个 Sentinel 判断主节点不可达时,标记为主观下线(SDOWN)。
- 多个 Sentinel 达成一致后,认为主节点客观下线(ODOWN)。
- 发起故障转移(failover),选举一个从节点为新主节点。
- 其余从节点重新指向新主节点。
哨兵配置文件
已知条件,哨兵节点每间隔1s
向主从节点发送一次ping。
三个哨兵均指向主节点(6379
),具体配置如下:
选举
sentinel1.conf
# 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
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
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
启动三个哨兵节点,如下图示:
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.confdocker 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.confdocker 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
# 主节点
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
)二子(6380
、6381
)。
此时,我们让主节点宕机
docker stop redis-master
以哨兵3节点为例,查看主节点宕机后,哨兵节点的选举过程,如下图:
- Subjectively Down(SDOWN)
- 当前 Sentinel 自己主观地认为 主节点 mymaster(即 192.168.10.9:6379)不可用了
- 这个判断是“本哨兵自己觉得”,是单方面的判断
- Objectively Down(ODOWN)
- 表示已经达到法定票数(quorum),多个 Sentinel 一致认为主节点真的挂了
- quorum 2/2 表示:当前已有 2 个哨兵都同意主节点宕机,而 Sentinel 配置中设置的 quorum 是 2(注意,哨兵1和2,此处是3/2,应该是某些不可抗力因素导致)
- 哨兵进入了一个新的故障转移纪元(
epoch
),编号为 1- 每次进行主节点切换时,都会开始一个新的 epoch,用于区分多次 failover 过程;
- 每个 Sentinel 会在其内部状态中记录当前 epoch;
- epoch 是分布式系统中常用的“版本”概念,避免重复选主等问题。
- 哨兵发起一次尝试性的 选举流程(
failover
),准备开始主从切换流程 - …(投票过程)
- 哨兵节点更新自己的配置文件(依据选举的主节点信息)
- 哨兵正式宣布
7380
为主节点 6381
配置为6380
的从节点6379
配置为6380
的从节点
此时查看 6380
已经是主节点
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
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
6379(旧主) ─┐ → 掉线│
Sentinel 投票 → 6380(新主)│┌──┴────────┐↓ ↓6381 6379(原副本) (变 slave)↑172.17.0.6:6381 也加入从节点6379 又挂了,+sdown slave
哨兵Sentinel的优缺点
✅ 优点(相比主从):
- 自动故障转移:主节点宕机后,哨兵自动选举一个从节点为新的主节点。
- 高可用支持:支持对主从架构的监控、通知、故障恢复。
- 运维成本低:比纯主从更自动化,降低人为干预。
❌ 弊端:
- 写仍是单点瓶颈:无论主节点自动切换多少次,写能力仍受限于单个主节点。
- 扩展性不足:不能横向扩展写能力,数据量过大时,主节点内存也会成为瓶颈。
- 数据分片不支持:所有节点都保存完整数据副本,浪费内存资源,无法水平扩展。
由以上哨兵模式的缺点,下一节将引入集群模式,敬请期待。