Redis Sentinel 模式最少几个Sentinel节点

Redis Sentinel 模式是一个Redis官方提供的高可用解决方案,其主要作用是在众多主从节点之间进行服务治理,比如:master宕机了,Sentinel的职责就是选举一个Slave服务为master,继续提供服务。网络上讲了很多理论,突然有人问我:Redis Sentinel最少可以起多少个Sentinel。

我个人理解这个东西可以分为两种情况讨论:

  1. 实际情况,其实单纯从代码的情况,其实一个Sentinel就能完成主观下线(sdown,Subjectively Down),客观下线(odown, Objectively Down 的判断,自动发现 Sentinel 和从服务器,并且完成故障转移
    下面是我做的一个实验:

在这里插入图片描述
sentinel的配置文件如下:
sentinel.conf

sentinel monitor mymaster 127.0.0.1 63792 1
sentinel down-after-milliseconds mymaster 6000
sentinel config-epoch mymaster 1

Sentinel 只有一个节点。
如果这个时候我kill掉端口为6379的master节点。结果如下:
在这里插入图片描述
上图的解释如下:

+reset-master <instance details> -- 当master被重置时.
+slave <instance details> -- 当检测到一个slave并添加进slave列表时.
+failover-state-reconf-slaves <instance details> -- Failover状态变为reconf-slaves状态时
+failover-detected <instance details> -- 当failover发生时
+slave-reconf-sent <instance details> -- sentinel发送SLAVEOF命令把它重新配置时
+slave-reconf-inprog <instance details> -- slave被重新配置为另外一个master的slave,但数据复制还未发生时。
+slave-reconf-done <instance details> -- slave被重新配置为另外一个master的slave并且数据复制已经与master同步时。
-dup-sentinel <instance details> -- 删除指定master上的冗余sentinel时 (当一个sentinel重新启动时,可能会发生这个事件).
+sentinel <instance details> -- 当master增加了一个sentinel时。
+sdown <instance details> -- 进入SDOWN状态时;
-sdown <instance details> -- 离开SDOWN状态时。
+odown <instance details> -- 进入ODOWN状态时。
-odown <instance details> -- 离开ODOWN状态时。
+new-epoch <instance details> -- 当前配置版本被更新时。
+try-failover <instance details> -- 达到failover条件,正等待其他sentinel的选举。
+elected-leader <instance details> -- 被选举为去执行failover的时候。
+failover-state-select-slave <instance details> -- 开始要选择一个slave当选新master时。
no-good-slave <instance details> -- 没有合适的slave来担当新master
selected-slave <instance details> -- 找到了一个适合的slave来担当新master
failover-state-send-slaveof-noone <instance details> -- 当把选择为新master的slave的身份进行切换的时候。
failover-end-for-timeout <instance details> -- failover由于超时而失败时。
failover-end <instance details> -- failover成功完成时。
switch-master <master name> <oldip> <oldport> <newip> <newport> -- 当master的地址发生变化时。通常这是客户端最感兴趣的消息了。
+tilt -- 进入Tilt模式。
-tilt -- 退出Tilt模式。

master 6379宕机,slave2升为master。
在这里插入图片描述

  1. 另外一种是实际生产情况。
    我们先来看看Redis的sentinel.conf配置文件解释。
# 设置端口
port 26379
# 是否守护进程启动
 daemonize no
# 守护进程运行的时候需要保留pidfile
pidfile /var/run/redis-sentinel.pid
# 日志文件
logfile "/root/log/sentinel.log"
## sentinel monitor master-group-name hostname port quorum
## quorum的解释如下:
 ##(1)至少多少个哨兵要一致同意,master进程挂掉了,或者slave进程挂掉了,或者要启动一个故障转移操作
## (2)quorum是用来识别故障的,真正执行故障转移的时候,还是要在哨兵集群执行选举,选举一个哨兵进程出来执行故障转移操作
## (3)假设有5个哨兵,quorum设置了2,那么如果5个哨兵中的2个都认为master挂掉了; 2个哨兵中的一个就会做一个选举,选举一个哨兵出来,执行故障转移; 如果5个哨兵中有3个哨兵都是运行的,那么故障转移才会被允许执行。
# 原文是:Note that whatever is the ODOWN quorum, a Sentinel will require to
# be selected by the majority of the known Sentinels in order to
# start a failover, so no failover can be performed in minority.
sentinel monitor mymaster 127.0.0.1 6379 3

# down-after-milliseconds,超过多少毫秒跟一个redis实例断了连接(ping不通),哨兵就可能认为这个redis实例挂了
sentinel down-after-milliseconds mymaster 30000

# parallel-syncs,新的master别切换之后,同时有多少个slave被切换到去连接新master,重新做同步,数字越低,花费的时间越多
# 比如:master宕机了,4个slave中有1个切换成了master,剩下3个slave就要挂到新的master上面去
# 这个时候,如果parallel-syncs是1,那么3个slave,一个一个地挂接到新的master上面去,1个挂接完,而且从新的master sync完数据之后,再挂接下一个。
# 如果parallel-syncs是3,那么一次性就会把所有slave挂接到新的master上去
sentinel parallel-syncs mymaster 1

#failover-timeout,执行故障转移的timeout超时时长,Default is 3 minutes.
sentinel failover-timeout mymaster 180000

首先我们回归问题:Redis Sentinel 模式最少几个Sentinel节点。
我们上面已经从代码的角度考虑了,其实一个sentinel就可以完成所有的功能,但是我们使用了Sentinel就是为了高可用。
高可用的概念可以参考CAP 理论十二年回顾。我的理解是CAP中,CAP就算各自有100分,其实我们生成环境也并不意味着一样要三个都100分,我们要根据自己的情况来做取舍。比如高可用1年360天,只是10s钟几十个顾客发生了不可用,我觉得这个整体看也是高可用的。
那么回归我们的Redis哨兵,高可用其实我怎么样处理呢?

上面的部署方案会存在着一个问题:sentinel和master同在一个机器上。
假设sentinel和master同在一个机器上其他3个slave在另外3台机器上,此时网络出现分区,sentinel和master被分割出去了,那么三台slave就无sentinel了。由此可以衍生出问题 slave保留的是旧数据,客户端分片读到这里读不到新的数据,从而到处业务处理错误,造成不可挽回的损失。

假设现在有2个sentinel。
如果哨兵集群仅仅部署了个2个哨兵实例,quorum=1

+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+
node1           node2

Configuration: quorum = 1

master宕机,s1和s2中只要有1个哨兵认为master宕机就可以还行切换,同时s1和s2中会选举出一个哨兵来执行故障转移

同时这个时候,需要majority,也就是大多数哨兵都是运行的,2个哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=3),2个哨兵都运行着,就可以允许执行故障转移。这里多提一点,一般节点和sentinel都用奇数个节点,有利于防止脑裂。

majority计算如下:

int sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {
   dictIterator *di;
   dictEntry *de;
   int usable = 1; /* Number of usable Sentinels. Init to 1 to count myself. */
   int result = SENTINEL_ISQR_OK;
   int voters = dictSize(master->sentinels)+1; /* Known Sentinels + myself. */

   di = dictGetIterator(master->sentinels);
   while((de = dictNext(di)) != NULL) {
       sentinelRedisInstance *ri = dictGetVal(de);

       if (ri->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;
       usable++;
   }
   dictReleaseIterator(di);

   if (usable < (int)master->quorum) result |= SENTINEL_ISQR_NOQUORUM;
   if (usable < voters/2+1) result |= SENTINEL_ISQR_NOAUTH;
   if (usableptr) *usableptr = usable;
   return result;
}

majority=voters/2+1

但是如果整个M1和S1运行的机器宕机了,那么哨兵只有1个了,此时就没有majority来允许执行故障转移,虽然另外一台机器还有一个R1,但是故障转移不会执行。

如果两个节点集群如下:

+----+          +----+         +----+
| S1 |----------| M1 |---------| S1 |
+----+          +----+         +----+
node1           node2	       node3	 
                  | 
                  |
                +----+  
                | R1 |
                +----+

如果node1节点宕机,而且M1 也宕机,这个时候就会出现R1不可用,即整个redis不可用的情况。而且sentinel消耗的资源并不多,不需要单独部署一台机器,否则就有点浪费了。
但是这种情况也比只有一台sentinel的时候可用性更加高。
用100分来打比喻,如果一个sentinel的时候是98分(即98%高可用),那么两个的sentinel的时候就是99分(99%高可用)。

如果是经典的3节点哨兵集群

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2。
majority=2(majority不能配置,由redis自行计算所得。)
正常生产环境一般部署如上。
如果M1所在机器宕机了,那么三个哨兵还剩下2个,S2和S3可以一致认为master宕机,然后选举出一个来执行故障转移

同时3个哨兵的majority是2,所以还剩下的2个哨兵运行着,就可以允许执行故障转移。
这就是经典的sentinel3个节点的集群。节省资源的同时又满足了高可用。
如果是100分的话,上面的可用性就能等到(99.9%)。
当然现实情况肯定要根据自己的项目需要而且配置,Redis的主从备份,分片机制等其实并没有ElasticSearch做的那么简单易用。
所以我个人觉得Redis正式上环境,最少又3个sentinel节点。

检查哨兵状态

redis-cli -h 192.168.31.187 -p 5000
sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster
SENTINEL get-master-addr-by-name mymaster

参考:
CAP 理论十二年回顾:"规则"变了 ,https://www.infoq.cn/article/cap-twelve-years-later-how-the-rules-have-changed/
Redis Sentinel机制与用法(一)https://www.cnblogs.com/zhoujinyi/p/5569462.html

### Redis Sentinel 模式的配置与工作原理 #### 1. Redis Sentinel 的基本概念 Redis Sentinel 是一种高可用性解决方案,主要用于监控 Redis 主从实例的状态,并在主节点发生故障时执行自动故障转移。这种机制可以显著提高系统的可靠性,确保即使在单点故障的情况下,服务仍能正常运行[^3]。 #### 2. 工作原理详解 Redis Sentinel 的核心功能包括以下几个方面: - **监控 (Monitoring)** Sentinel 节点会持续不断地检查主服务器和从服务器是否按预期工作。如果发现主服务器不可用,则触发后续操作[^1]。 - **通知 (Notification)** 当被监控的某个 Redis 实例出现问题时,Sentinel 可以向管理员或其他应用程序发送警报,以便及时采取措施[^2]。 - **自动故障转移 (Automatic Failover)** 如果主服务器无法继续工作,Sentinel 将启动选举流程,选择一个合适的从服务器升级为主服务器,并更新客户端连接信息。 - **配置提供者 (Configuration Provider)** 客户端可以通过 Sentinel 获取当前最新的主服务器地址,从而动态调整自己的连接目标。 #### 3. 配置方法 以下是 Redis Sentinel 的典型配置过程及其关键参数说明: ##### (1)安装与初始化 假设已经部署好 RedisSentinel 所需环境,创建 `sentinel.conf` 文件来定义哨兵的行为规则。以下是一个简单的配置文件示例: ```bash port 26379 # 设置 Sentinel 运行的端口号 daemonize yes # 后台运行 logfile "/var/log/redis/sentinel.log" # 日志路径 dir /tmp # 数据存储目录 # 监控名为 mymaster 的主从集群,其中 master 地址为 127.0.0.1:6379, # 至少需要 2 个 Sentinel 协议确认才能判定主节点下线 sentinel monitor mymaster 127.0.0.1 6379 2 # 故障切换超时时间设置为 180 秒 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 180000 ``` 上述配置中: - `sentinel monitor`: 表明要监视哪个主库(名称、IP、端口),以及至少多少个 Sentinel 认可该判断才生效。 - `down-after-milliseconds`: 设定多长时间未收到回复视为断开链接。 - `failover-timeout`: 控制整个故障转移的最大允许耗时时长。 ##### (2)启动多个 Sentinel 实例 为了增强健壮性,通常建议在同一网络环境下部署三个或更多 Sentinel 实例形成多数派决策机制。每个 Sentinel 使用相同的配置文件即可独立运行。 命令如下所示: ```bash redis-sentinel /path/to/sentinel.conf ``` #### 4. 自动故障转移的具体流程 当主服务器宕机后,Sentinel 群体会按照既定逻辑完成以下步骤: 1. 多数 Sentinel 达成一致意见认为原 Master 不再可达; 2. 在存活 Slave 中挑选最适合作为新 Master 的候选对象; 3. 更新所有 Client 对应的新 Master IP 和 Port; 4. 修改其他 Slaves 关联关系使其同步到新的 Master 上。 --- ### 示例代码:验证 Sentinel 功能的小型 Python 应用程序 下面展示如何利用 redis-py 库编写一段脚本测试 Sentinel 是否成功接管失败的服务。 ```python import redis from redis.sentinel import Sentinel def connect_to_redis_sentinel(): sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1) master = sentinel.master_for('mymaster', db=0, password=None, socket_timeout=0.1) try: result = master.set('test_key', 'value') value = master.get('test_key').decode() print(f"Successfully set key with value {value}") except Exception as e: print("Error occurred:", str(e)) if __name__ == "__main__": connect_to_redis_sentinel() ``` 此段代码展示了通过 Sentinel API 来获取当前有效的 Master 并尝试写入数据的过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值