Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理
共 8281字,需浏览 17分钟
· 2021-06-02
概要
我们知道「主从复制是高可用的基石」,从库宕机依然可以将请求发送给主库或者其他从库,但是 Master 宕机,只能响应读操作,写请求无法再执行。
所以主从复制架构面临一个严峻问题,主库挂了,无法执行「写操作」,无法自动选择一个 Slave 切换为 Master,也就是无法故障自动切换。
深夜与女朋友么么哒……(此处省略 10000 字),突然宕机,总不能提起裤子从床上爬起来手工进行主从切换,再通知其他程序员把地址重新改成新主库上线。
如此一折腾自己已被女友切换成前男友了,万万使不得。所以我们必须有一个高可用的方案,为此,Redis 官方提供一个高可用方案——哨兵(Sentinel)。
开篇寄语
“ 技术的迭代非常的快,但是从技术中沉淀下来的思维却是受益终生的。所以不要担心什么中年危机,那些担心中年危机的人通常很难成长起来。只要我们成长,只要我们的认知在不断突破,就不用担心中年危机,这个世界始终是需要那些优秀人才的。 ”
什么是哨兵(Sentinel)
“ 65 哥:码哥,虽然我没女朋友,但是,未雨绸缪我要掌握这个哨兵模式,防止当深夜与女朋友么么哒被打扰,你快说说哨兵的实现原理吧。 ”
如何判断掌门真的挂了,有可能假死; 到底选择哪一个武当子弟作为新掌门? 通过新闻发布会将新掌门的相关信息通知到所有武当弟子(slave 和 master)和整个武林(客户端)。
哨兵机制的主要任务
监控:持续监控 master 、slave 是否处于预期工作状态。 自动切换主库:当 Master 运行故障,哨兵启动自动故障恢复流程:从 slave 中选择一台作为新 master。 通知:让 slave 执行 replicaof ,与新的 master 同步;并且通知客户端与新 master 建立连接。
“ 65 哥:那到底「哨兵」这个神秘部门是如何实现这三个能力的? ”
监控
有效回复:返回 +PONG、-LOADING、-MASTERDOWN 任何一种; 无效回复:有效回复之外的回复,或者指定时间内返回任何回复。
“ 65 哥:哨兵如何判断「掌门」嗝屁呢?掌门诈尸咋办? ”
主观下线
客观下线
主观下线与客观下线的区别
# sentinel monitor <master-name> <master-host> <master-port> <quorum>
# 举例如下:
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel monitor:代表监控。 mymaster:代表主节点的名称,可以自定义。 192.168.11.128:代表监控的主节点 ip,6379 代表端口。 2:法定数量,代表只有两个或两个以上的哨兵认为主节点不可用的时候,才会把 master 设置为客观下线状态,然后进行 failover 操作。
自动切换主库
“ 65 哥:既然判断 master 客观下线了,那就要从选出一个新掌门人了吧。 ”
筛选条件
“ 65 哥:那都有哪些筛选条件呀? ”
从库当前在线状态,下线的直接丢弃; 评估之前的网络连接状态 down-after-milliseconds \* 10
:如果从库总是和主库断连,而且断连次数超出了一定的阈值(10 次),我们就有理由相信,这个从库的网络状况并不是太好,就可以把这个从库筛掉了。
打分
slave 优先级,通过 slave-priority 配置项,给不同的从库设置不同优先级(后台有人没办法),优先级高的直接晋级为新 master 掌门。 slave_repl_offset
与master_repl_offset
进度差距(谁的武功与之前掌门的功夫越接近谁就更牛逼),如果都一样,那就继续下一个规则。其实就是比较 slave 与旧 master 复制进度的差距;slave runID,在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库。(论资排辈,根据 runID 的创建时间来判断,时间早的上位);
通知
“ 65 哥:为啥还要召开新闻发布会呢? ”
哨兵集群工作原理
sentinel monitor <master-name> <ip> <redis-port> <quorum>
pub/sub 实现哨兵间通信和发现 slave
“ 65 哥:哨兵之间是如何知道彼此的? ”
pub/sub
发布/订阅机制。__sentinel__:hello
的专用通道,用于哨兵之间发布和订阅消息。这就好比是 __sentinel__:hello
微信群,哨兵利用 master 建立的微信群发布自己的消息,同时关注其他哨兵发布的消息。“ 65 哥:哨兵之间虽然建立连接了,但是还需要和 slave 建立连接,不然没法监控他们呀,如何知道 slave 并监控他们的? ”
INFO
命令, master 掌门自然是知道自己门下所有的 salve 小弟的。所以 master 接收到命令后,便将 slave 列表告诉哨兵。INFO
命令,Master 就把 slave 列表返回给哨兵 2,哨兵 2 便根据 slave 列表连接信息与每一个 slave 建立连接,并基于此连接实现持续监控。选择哨兵执行主从切换
“ 65 哥:master 嗝屁了以后,哨兵这么多,那到底让哪一个哨兵来执行新 master 切换呢? ”
is-master-down-by-addr
命令,好基友则根据自己跟 master 之间的连接状况分别响应 Y
或者 N
,Y
表示赞成票, N
就是反对。sentinel monitor <master-name> <ip> <redis-port> <quorum>
获得其他哨兵基友过半的赞成票; 赞成票的数量还要大于等于配置文件的 quorum 的值。
通过 pub/sub 实现客户端事件通知
“ 65 哥:新 master 选出来了,要怎么公示天下呢? ”
master 下线事件
+sdown:进入“主观下线”状态; -sdown:退出“主观下线”状态; +odown:进入“客观下线”状态; -odown:退出“客观下线”状态;
slave 重新配置事件
+slave-reconf-sent:哨兵发送 replicaof 命令重新配置从库; +slave-reconf-inprog:slave 配置了新 master,但是尚未进行同步; +slave-reconf-done:slave 配置了新 master,并与新 master 完成了数据同步;
新主库切换
SUBSCRIBE +odown
注意事项与配置说明
down-after-milliseconds
down-after-milliseconds * 10
总结
监控 master 与 slave 运行状态,判断是否客观下线; master 客观下线后,选择一个 slave 切换成 master; 通知 slave 和客户端新 master 信息。
基于 pub/sub 机制实现哨兵集群之间的通信; 基于 INFO 命令获取 slave 列表,帮助 哨兵与 slave 建立连接; 通过哨兵的 pub/sub,实现了与客户端和哨兵之间的事件通知。
[1][redis设计与实现] 黄健宏
[2][redis核心技术与实战] https://time.geekbang.org/column/article/274483
[3][redis 深度历险:核心原理与应用实战] https://juejin.cn/book/6844733724618129422/section/6844733724722987021
[4][redis 专题:深入解读哨兵模式] https://juejin.cn/post/6934984432273063967#heading-0
[5][redis哨兵原理,我忍你很久了!] https://www.modb.pro/db/25926
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️