redis: sentinel

1.概述

redis主从复制解决了单机下数据丢失的问题,在一主多从的结构下,倘若master出现故障,slaves仍然有数据备份。此时一个自然而然的想法就涌现出来了:在master不可用的情况下,能否重新调整主从关系,从slave中选取一个服务器作为新的master,从而实现redis的高可用。sentinel就是这样一种解决方案:由一组哨兵(sentinel)实例组成一个sentinel系统,该系统保证其自身高可用性的同时,监控redis主服务器和该主服务器所属的从服务器,当主服务器下线时长超过阈值之后,由sentinel系统挑选一个从服务器,将该服务器升级为新的主服务器,完成故障转移。同时,sentinel还持续监控已下线的服务器,当他重新上线时,将该服务器设为新的master下的slave。

sentinel系统的运行流程如图:

  1. 假设现有一个master和3各slave。通过配置sentinel系统,使其监控这些服务器


    sentinel系统监控master和其所属的slave
  2. 当master服务器(server1)下线, 主从复制将会被终止。同时,sentinel感知到server1下线。


    主服务器下线

    3.master下线时间超过阈值,sentinel系统开始故障转移。在slave中选取一个服务器(如server2),作为新的master,让其他的服务器作为server2的从服务器。另一边,sentinel持续监控server1的状态。


    选举新的主服务器,持续监控下线服务器
  3. 当server1重新上线时,sentinel通过SLAVEOF命令将其设置为server2的从服务器。


    下线主机重新上线,降级为从服务器

2.sentinel启动运行全流程

2.1启动sentinel

创建一个类型为sentinel的redis服务器。它本质上仍然是一个redis服务器,但其工作方式和普通redis服务器不同,主要体现在它需要维护各master和master下slave的在线信息。


image.png

1.1. 替换服务器代码为Sentinel专用代码Redis_Server_Port --> Redis_Sentinel_Port; redisCommandTable --> sentinelcmds。
1.2. 由服务器初始化Sentinel状态,创建一个sentinelState结构,主要维护了一个保存masters信息的字典。
1.5. 服务器读取sentinel.conf文件,完成Sentinel中masters属性的配置。假设在配置文件中配置了master1和master2,那么masters的状态如图。


image.png

1.4. 创建与各master的连接,准备与master通信

2.2. 获取主服务器信息

2.1. 主服务器本身的信息: run_id: xxx, role:master 
2.2 slave信息 ip, port, state, offset ...
image.png

获取到服务器信息之后,即可更新服务器实例信息,如下图:


image.png

2.3. 获取从服务器信息

当有新的从服务器通过SLAVEOF成为主服务器的slave时,master的回复信息终将会包含该服务器的信息。Sentinel一方面要为该服务器创建实例结构, 另一方面还需要创建到该服务器的命令连接和订阅连接。连接创建后,sentinel每10秒向从服务器发送INFO命令,获取从服务器的信息,包括run_id, role, masterhost: master_port, 复制偏移量...

2.4. 以一定频率向主、从服务器发送信息

每2秒向所有被监视的主、从服务器发送 PUBLISH sentinel: hello "<...>"命令。

2.5. 接收主、从服务器的信息

通过订阅连接,向服务器发送 SUBSCRIBE sentinel:hello命令。一台sentinel像某台master/slave发送的信息也会被其他订阅了该服务器的sentinel收到。该功能的作用在于:使各个sentinel之间能通过主/从服务器相互通信。 根据收到的消息,如果是自己发送的,那么就丢弃;如果是其他sentinel发送的,就根据信息中的各个参数更新主服务器的实例结构,更新sentinels字典,此时各个sentinel中就可以保存彼此的ip:port,接下来创建链接并相互通信就顺理成章了。

image.png

image.png

image.png

2.6. 检测下线状态

2.6.1 主观下线状态

sentinel默认每秒向所有与他创建了连接的实例(master, slave, sentinel)发送PING命令,通过回复状态来判断实例是否在线。每个sentinel对服务器实例的下线判断都是依靠它自身与服务器之间的连接,有可能二者之间通信不顺畅,导致该sentinel判断对方下线,但并不意味着对方真的下线了,因此这种情况称之为主观下线;实例是否真的下线了,要依靠所有sentinel投票。


image.png

回复内容只有3种有效: -PONG, -LOADING, -MASTERDOWN
如果一个实例在一定时间内,连续向sentinel返回无效回复,则sentinel修改该实例对应的状态,将其标记为主观下线。

2.6.2 客观下线状态

当一个sentinel将主服务器标记为主观下线状态之后,会向其他监视该服务器的sentinel发送请求,看他们是否也认为该服务器处于下线状态。当认为下线的sentinel超过配置的阈值时,表明客观下线,将主服务器实例标记为客观下线状态

2.7. 选举sentinel leader

当sentinel将一个主服务器被判定为客观下线之后,会发送请求给监视它的各sentinel,选举出一个leader sentinel,然后由leader sentinel来进行故障转移。

Sentinel集群正常运行的时候每个节点epoch相同,当需要故障转移的时候会在集群中选出Leader执行故障转移操作。Sentinel采用了Raft协议实现了Sentinel间选举Leader的算法,不过也不完全跟论文描述的步骤一致。Sentinel集群运行过程中故障转移完成,所有Sentinel又会恢复平等。Leader仅仅是故障转移操作出现的角色。

选举流程

  • 1、某个Sentinel认定master客观下线的节点后,该Sentinel会先看看自己有没有投过票,如果自己已经投过票给其他Sentinel了,在2倍故障转移的超时时间自己就不会成为Leader。相当于它是一个Follower。
  • 2、如果该Sentinel还没投过票,那么它就成为Candidate。
  • 3、和Raft协议描述的一样,成为Candidate,Sentinel需要完成几件事情
    • 1)更新故障转移状态为start
    • 2)当前epoch加1,相当于进入一个新term,在Sentinel中epoch就是Raft协议中的term。
    • 3)更新自己的超时时间为当前时间随机加上一段时间,随机时间为1s内的随机毫秒数。
    • 4)向其他节点发送is-master-down-by-addr命令请求投票。命令会带上自己的epoch。
    • 5)给自己投一票,在Sentinel中,投票的方式是把自己master结构体里的leader和leader_epoch改成投给的Sentinel和它的epoch。
  • 4、其他Sentinel会收到Candidate的is-master-down-by-addr命令。如果Sentinel当前epoch和Candidate传给他的epoch一样,他在本轮把票投给了其他Candidate。投过票给别的Sentinel后,在当前epoch内自己就只能成为Follower。
  • 5、Candidate会不断的统计自己的票数,直到他发现认同他成为Leader的票数超过一半而且超过它配置的quorum(quorum可以参考《redis sentinel设计与实现》)。Sentinel比Raft协议增加了quorum,这样一个Sentinel能否当选Leader还取决于它配置的quorum。
  • 6、如果在一个选举时间内,Candidate没有获得超过一半且超过它配置的quorum的票数,自己的这次选举就失败了。
  • 7、如果在一个epoch内,没有一个Candidate获得更多的票数。那么等待超过2倍故障转移的超时时间后,Candidate增加epoch重新投票。
  • 8、如果某个Candidate获得超过一半且超过它配置的quorum的票数,那么它就成为了Leader。
  • 9、与Raft协议不同,Leader并不会把自己成为Leader的消息发给其他Sentinel。其他Sentinel等待Leader从slave选出master后,检测到新的master正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程。
    ref:Raft协议实战之Redis Sentinel的选举Leader源码解析
    leader选举

2.8. 故障转移

8.1. 由leader sentinel重新选取新的master
8.2 修改从服务器的复制目标
8.3 监控旧的master,上线后将其设置为新的master下的slave

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容