Redis-Sentinel 简介
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,可以实现:
- Master宕机时自动切换到从
- 如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端);
运行sentinel有两种方式:redis-sentinel /path/to/sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
➤ Sentinel 特性:
- 多个 Sentinel 实例组成一个集群,一个 Sentinel 集群可监视多个 Redis Master 实例;
- Sentinel 的数据通信:
- Sentinel 通过向 Redis Master 发送
INFO
命令, 获取它所有的 Slava - Sentinel 会订阅自己监视的 Redis Master 的
sentilel:hello
频道, 同时向该 Redis 的频道发送消息, 消息包括 Sentinel 自己的 IP:Port 等, 这样其他的 Sentinel 也会收到此消息, Sentinel 通过发布/订阅的广播方式感知其他 Sentinel 的存在
- Sentinel 通过向 Redis Master 发送
➤ 配置文件解读:
# 定义一个'mymaster', 2表示两个Sentinel认为Master挂掉了才算 |
Sentinel 如何执行主从 fail-over
Sentinel 发现主节点宕机, 将会执行主从的 fail-over、并通知 Client 变更:
- 发现并判断宕机: Sentinel 每秒向监控的 Redis master实例发送
PING
命令测试其是否宕机, 如果某个主Redis节点返回了错误结果或者Timeout, Sentinel 认为该节点是”主观下线”(SDOWN), 如果 quorum个 Sentinel都把这个节点标记为下线, 那么 Sentinel master将把这个 Redis节点的状态则被标记为”客观下线”(ODOWN), 这时才开始执行fail-over; - 执行 fail-over:所有 Sentinel 选举出一个 Leader,由 Sentinel Leader 执行 redis 主节点的 fail-over
- (1)从 Slave 中选取 master:首先按照所有 Slave 的优先级, 如果优先级相同, 则比较 Slave 的复制的下标, 哪个 Slave 复制进度最接近则选举为 Master, 如果优先级和复制下标都相同, 则选进程 ID 较小的,作为新 Master;
- (2)Sentinel 向新的 Master 发送
SLAVEOF NO ONE
, 然后依次向其他的 Slave 发送SLAVEOF
命令让其跟随新的 Master, 然后 Slave 向新 Master 发送SYNC
指令开始同步数据, 一个 Slave 完成上述操作后, 开始下一个 Slave… - Sentinel leader 把最新的 Redis 配置广播给其他 Sentinel
- Sentinel 通知调用方:
- Sentinel 提供了很多频道,例如
+switch-master
频道,主从切换完成后,会在这个频道发布新主的 IP:Port;
- 客户端(jedis)订阅这些频道,即可获取 Redis 集群的变更消息;
- Sentinel 提供了很多频道,例如
Sentinel 如何选举 leader
➤ Sentinel的选举何时触发:
- 在某个 Redis Master节点被认定客观下线后, Sentinel需要选举出一个 Leader, 由 Leader完成 故障转移(从一堆Redis 的Slave节点中选出master, 以及 Slave的重新配置和同步).
- 或者当 Leader Sentinel节点失效时, 也会开始一轮选举
- 无论哪种选举, 当选举完成后, 配置纪元(configuration epoch)都会增加一次, 表示一轮选举完成
➤ Sentinel Leader选举步骤:
- 当某个 Sentinel 节点认为 “Sentinel master” 客观下线后, 它会做下面几件事情:
- 把故障转移状态设置为true
- 自己从 Follower 角色变为 Candidate(候选者)
- 给自己投一票
- 当前的配置纪元+1, 并向其他 Sentinel节点发送
SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
指令, 解释一下这个指令,<ip> <port>
表示客观下线的 master,<current_epoch>
表示配置纪元, 后面的<runid>
就是这个Sentinel自己的 runid(唯一标识)
- 当其他的 Sentinel 节点收到
is-master-down-by-addr
指令后, 会比较指令发来的配置纪元(epoch)和自己保存的配置纪元, 如果发来的配置纪元比自己存储的 epoch 更大(表示这是一次新的投票纪元), 收到is-master-down-by-addr
指令的节点会把自己的选票投给这个发出is-master-down-by-addr
指令的 Candidate, 并更新自己的配置纪元, 在一个配置纪元内一个 Follower 只能投一篇. 然后 Follower 给这个 Candidate 回复, 回复内容就是 Candidate 的 runid - Candidate 等待来自 Follower 的回复, 如果发现回复内容就是自己的 runid, 会给本轮选举(当前配置纪元)自己选票+1. 如果自己的选票大于半数(这里应该
can-failover
的节点数的一半), 并且选票大于 quorum, 则认为自己当选;
@tldr:当选条件是票数>半数的哨兵实例数,且选票数> quorum(客观下线)
Reference
- Redis 高可用部署方案 | hoxis’ blog
- Redis 哨兵节点之间相互自动发现机制(自动重写哨兵节点的配置文件) - MSSQL123 - 博客园
- 在Redis Sentinel环境下,jedis该如何配置 - iVictor - 博客园
- redis实现HA(High Available)的两种实现方式-Sentinel与Keepalived_数据库_路漫漫,水迢迢-CSDN博客
- Redis 高可用部署方案 | hoxis’ blog
- 浅谈Redis Sentinel 哨兵-选举领头Sentinel和故障转移 - 知乎
- Raft协议实战之Redis Sentinel的选举Leader源码解析 - 云+社区 - 腾讯云