《Redis系列》第七章:高可用之哨兵模式(Sentinel)

一、Redis Sentinel原理

1.1 概述

当我们部署的redis集群在运行过程中,如果主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。

Sentinel(哨兵)是用于监控redis集群中Master状态的工具,是一个独立的进程,作为进程,它会独立运行, 它是Redis 的高可用性解决方案,可以帮助我们管理集群,哨兵,sentinel可以让redis实现主从复制,当一个集群中的master失效之后,sentinel可以选举出一个新的master用于自动接替master的工作,集群中的其他redis服务器自动指向新的master同步数据。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第1张图片

1.2 Redis故障切换过程图示

假设主服务器宕机,哨兵1会先检测这个结果,系统不会立马进行 failover 过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线,当后面的哨兵检测到主服务器也不可用,并且达到一定值以后,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功以后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第2张图片

1.3 Sentinel作用

1)  Master 状态检测

2)如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave

3)Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换。

1.4 Sentinel 工作流程

1)每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个PING命令。
2)如果一个实例(instance)距离最后一次有效回复PING命令的时间超过 down-after-milliseconds 选项所指定的值,则这个实例会被Sentinel标记为主观下线。 
3)如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 
4)当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线。
5)在一般情况下,每个Sentinel 会以每10秒一次的频率向它已知的所有Master,Slave发送 INFO 命令。
6)当Master被Sentinel标记为客观下线时,Sentinel 向下线的 Master 的所有Slave发送 INFO命令的频率会从10秒一次改为每秒一次。 
7)若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。 若 Master重新向Sentinel 的PING命令返回有效回复,Master的主观下线状态就会被移除。

1.5 Sentinel的3个内部定时任务

1)每10s 每个Sentinel 会对master和slave执行info命令,这个任务达到两个目的: a)发现slave节点 b)确认主从关系

2)  每2秒每个sentinel通过master节点的channel交换信息,master节点有一个发布订阅的频道(_sentinel_:hello)。sentinel节点通过 _sentinel_:hello 频道进行信息交换(对节点的“看法“和自身的信息),达成共识

3)  每1秒每个Sentinel对其它sentinel和redis节点执行PING操作(相互监督),这个其实是一个心跳检测,是失败判定的依据。

1.6 主观下线SDOWN

所谓主观下线(Subjectively Down, 简称 SDOWN)指的是单个Sentinel实例对服务器做出的下线判断,即单个sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。
主观下线就是说如果服务器在 down-after-milliseconds 给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(SDOWN )。

sentinel会以每秒一次的频率向所有与其建立了命令连接的实例(master,从服务,其他sentinel)发ping命令,通过判断ping回复是有效回复,还是无效回复来判断是否在线(对该sentinel来说是“主观在线”)。

当Sentinel 发送PING后,以下回复之一都被认为是合法的:

PING replied with +PONG.
       PING replied with -LOADING error.
       PING replied with -MASTERDOWN error.
       其它任何回复(或者根本没有回复)都是不合法的。
Sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度,如果实例在down-after-milliseconds毫秒内,返回的都是无效回复,那么sentinel回认为该实例已(主观)下线,修改其flags状态为SRI_S_DOWN。如果多个sentinel监视一个服务,有可能存在多个sentinel的down-after-milliseconds配置不同,这个在实际生产中要注意。

1.7 客观下线ODOWN

1)概念

客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断,然后开启failover。
客观下线就是说只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(ODOWN)。只有当master被认定为客观下线时,才会发生故障迁移

2)判断过程

当前 sentinel 通过发送 SENTINEL is-master-down-by-addr ip port current_epoch runid,(ip:主观下线的服务id,port:主观下线的服务端口,current_epoch:sentinel的纪元,runid:*表示检测服务下线状态,如果是sentinel 运行id,表示用来选举领头sentinel)来询问其它sentinel是否同意服务下线。
当其它的sentinel接收 当前sentinel 发来的is-master-down-by-addr后,提取参数,根据ip和端口,检测该服务时候在该sentinel 是否主观下线,并且回复is-master-down-by-addr,回复包含三个参数:down_state(1表示已下线,0表示未下线),leader_runid(领头sentinal id),leader_epoch(领头sentinel纪元),当前 sentinel接收到回复后,根据配置设置的下线最小数量,判断是否达到这个值,既认为该服务是否客观下线。

如果之后master又恢复正常使用了,那么这个状态就会相应的被清理掉

3)注意事项

客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作

1.8 Sentinel状态持久化

Sentinel的状态会被持久化地写入sentinel的配置文件中。每次当收到一个新的配置时,或者新创建一个配置时,配置会被持久化到硬盘中,并带上配置的版本戳。这意味着,可以安全的停止和重启sentinel进程

1.9 Sentinel 如何保证failover不冲突

Sentinel 通过版本号的方式来保证

当一个sentinel被授权后,它将会获得宕掉的master的一份最新配置版本号,当failover执行结束以后,这个版本号将会被用于最新的配置。因为大多数sentinel都已经知道该版本号已经被要执行failover的sentinel拿走了,所以其他的sentinel都不能再去使用这个版本号。这意味着,每次failover都会附带有一个独一无二的版本号。

一个failover要想被成功实行,sentinel必须能够向选为master的slave发送SLAVEOF NO ONE命令,然后能够通过INFO命令看到新master的配置信息。当将一个slave选举为master并发送SLAVEOF NO ONE后,即使其它的slave还没针对新master重新配置自己,failover也被认为是成功了的,然后所有sentinels将会发布新的配置信息。它将会把关于master的最新配置通过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置。

因为每一个配置都有一个版本号,所以以版本号最大的那个为标准。

举个例子:
假设有一个名为mymaster的地址为192.168.10.202:6379。一开始,集群中所有的sentinel都知道这个地址,于是为mymaster的配置打上版本号1。一段时候后mymaster死了,有一个sentinel被授权用版本号2对其进行failover。如果failover成功了,假设地址改为了192.168.10.202:9000,此时配置的版本号为2,进行failover的sentinel会将新配置广播给其他的sentinel,由于其他sentinel维护的版本号为1,发现新配置的版本号为2时,版本号变大了,说明配置更新了,于是就会采用最新的版本号为2的配置。

1.10 Sentinel的”仲裁会“

前面我们谈到,当一个master被sentinel集群监控时,需要为它指定一个参数,这个参数指定了当需要判决master为不可用,并且进行failover时,所需要的sentinel数量,可以称这个参数为票数

不过,当failover主备切换真正被触发后,failover并不会马上进行,还需要sentinel中的大多数sentinel授权后才可以进行failover。
当ODOWN时,failover被触发。failover一旦被触发,尝试去进行failover的sentinel会去获得“大多数”sentinel的授权(如果票数比大多数还要大的时候,则询问更多的sentinel)
这个区别看起来很微妙,但是很容易理解和使用。例如,集群中有5个sentinel,票数被设置为2,当2个sentinel认为一个master已经不可用了以后,将会触发failover,但是,进行failover的那个sentinel必须先获得至少3个sentinel的授权才可以实行failover。
如果票数被设置为5,要达到ODOWN状态,必须所有5个sentinel都主观认为master为不可用,要进行failover,那么得获得所有5个sentinel的授权。

1.11 Sentinel的领导者选择流程

一个redis服务被判断为客观下线时,多个监视该服务的sentinel协商,选举一个领头sentinel,对该redis服务进行故障转移操作。

为什么要选领导者?
     简单来说,就是因为只能有一个sentinel节点去完成故障转移。
     sentinel is-master-down-by-addr这个命令有两个作用,一是确认下线判定,二是进行领导者选举。

选举领头sentinel遵循以下规则:
     1)所有的sentinel都有公平被选举成领头的资格。
     2)所有的sentinel都有且只有一次将某个sentinel选举成领头的机会(在一轮选举中),一旦选举某个sentinel为领头,不能更改。
     3)Sentinel设置领头sentinel是先到先得,一旦当前sentinel设置了领头sentinel,以后要求设置sentinel为领头请求都会被拒绝。
     4)每个发现服务客观下线的sentinel,都会要求其他sentinel将自己设置成领头。
     5)当一个sentinel(源sentinel)向另一个sentinel(目sentinel)发送is-master-down-by-addr ip port current_epoch runid命令的时候,runid参数不是*,而是sentinel运行id,就表示源sentinel要求目标sentinel选举其为领头。
     6)源sentinel会检查目标sentinel对其要求设置成领头的回复,如果回复的leader_runid和leader_epoch为源sentinel,表示目标sentinel同意将源sentinel设置成领头。
     7)如果某个sentinel被半数以上的sentinel设置成领头,那么该sentinel既为领头。
     8)如果在限定时间内,没有选举出领头sentinel,暂定一段时间,再选举。
选举过程:
    1)每个做主观下线的sentinel节点向其他sentinel节点发送上面那条命令,要求将它设置为领导者。
    2)收到命令的sentinel节点如果还没有同意过其他的sentinel发送的命令(还未投过票),那么就会同意,否则拒绝。
    3)如果该sentinel节点发现自己的票数已经过半且达到了quorum的值,就会成为领导者
    4)如果这个过程出现多个sentinel成为领导者,则会等待一段时间重新选举。

1.12 Sentinel支持集群

只使用单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行。所以有必要将sentinel集群,这样有几个好处:
1)即使有一些sentinel进程宕掉了,依然可以进行redis集群的主备切换;
2)如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);
3)如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息。

1.13 Sentinel集群注意事项

1)只有Sentinel 集群中大多数服务器认定master主观下线时master才会被认定为客观下线,才可以进行故障迁移,也就是说,即使不管我们在sentinel monitor中设置的数是多少,就算是满足了该值,只要达不到大多数,就不会发生故障迁移。
2)官方建议sentinel至少部署三台,且分布在不同机器。这里主要考虑到sentinel的可用性,假如我们只部署了两台sentinel,且quorum设置为1,也可以实现自动故障迁移,但假如其中一台sentinel挂了,就永远不会触发自动故障迁移,因为永远达不到大多数sentinel认定master主观下线了。
3)sentinel monitor配置中的master IP尽量不要写127.0.0.1或localhost,因为客户端,如jedis获取master是根据这个获取的,若这样配置,jedis获取的ip则是127.0.0.1,这样就可能导致程序连接不上master
4)当sentinel 启动后会自动的修改sentinel.conf文件,如已发现的master的slave信息,和集群中其它sentinel 的信息等,这样即使重启sentinel也能保持原来的状态。注意,当集群服务器调整时,如更换sentinel的机器,或者新配置一个sentinel,请不要直接复制原来运行过得sentinel配置文件,因为其里面自动生成了以上说的那些信息,我们应该复制一个新的配置文件或者把自动生成的信息给删掉。
5)当发生故障迁移的时候,master的变更记录与slave更换master的修改会自动同步到redis的配置文件,这样即使重启redis也能保持变更后的状态。

1.14 Sentinel之间和Slaves之间的自动发现机制

虽然sentinel集群中各个sentinel都互相连接彼此来检查对方的可用性以及互相发送消息。但是你不用在任何一个sentinel配置任何其它的sentinel的节点。因为sentinel利用了master的发布/订阅机制去自动发现其它也监控了统一master的sentinel节点。
通过向名为__sentinel__:hello的管道中发送消息来实现。
同样,你也不需要在sentinel中配置某个master的所有slave的地址,sentinel会通过询问master来得到这些slave的地址的。
每个sentinel通过向每个master和slave的发布/订阅频道__sentinel__:hello每秒发送一次消息,来宣布它的存在。
每个sentinel也订阅了每个master和slave的频道__sentinel__:hello的内容,来发现未知的sentinel,当检测到了新的sentinel,则将其加入到自身维护的master监控列表中。
每个sentinel发送的消息中也包含了其当前维护的最新的master配置。如果某个sentinel发现
自己的配置版本低于接收到的配置版本,则会用新的配置更新自己的master配置。
在为一个master添加一个新的sentinel前,sentinel总是检查是否已经有sentinel与新的sentinel的进程号或者是地址是一样的。如果是那样,这个sentinel将会被删除,而把新的sentinel添加上去。

1.15 增加或删除Sentinel

由于有sentinel自动发现机制,所以添加一个sentinel到你的集群中非常容易,你所需要做的只是监控到某个Master上,然后新添加的sentinel就能获得其他sentinel的信息以及master所有的slaves。
如果你需要添加多个sentinel,建议你一个接着一个添加,这样可以预防网络隔离带来的问题。你可以每个30秒添加一个sentinel。最后你可以用SENTINEL MASTER mastername来检查一下是否所有的sentinel都已经监控到了master。
删除一个sentinel显得有点复杂:因为sentinel永远不会删除一个已经存在过的sentinel,即使它已经与组织失去联系很久了。
要想删除一个sentinel,应该遵循如下步骤:
1)停止所要删除的sentinel
2)发送一个SENTINEL RESET * 命令给所有其它的sentinel实例,如果你想要重置指定master上面的sentinel,只需要把*号改为特定的名字,注意,需要一个接一个发,每次发送的间隔不低于30秒。
3)检查一下所有的sentinels是否都有一致的当前sentinel数。使用SENTINEL MASTER mastername 来查询。

1.16 删除旧master或者不可达slave

sentinel永远会记录好一个Master的slaves,即使slave已经与组织失联好久了。这是很有用的,因为sentinel集群必须有能力把一个恢复可用的slave进行重新配置。
并且,failover后,失效的master将会被标记为新master的一个slave,这样的话,当它变得可用时,就会从新master上复制数据。
然后,有时候你想要永久地删除掉一个slave(有可能它曾经是个master),你只需要发送一个SENTINEL RESET master命令给所有的sentinels,它们将会更新列表里能够正确地复制master数据的slave。

1.17 Slave选举与优先级

当一个sentinel准备好了要进行failover,并且收到了其他sentinel的授权,那么就需要选举出一个合适的slave来做为新的master。

slave的选举主要会评估slave的以下几个方面:
1)与master断开连接的次数
2)Slave的优先级
3)数据复制的下标(用来评估slave当前拥有多少master的数据)
4)进程ID

如果一个slave与master失去联系超过10次,并且每次都超过了配置的最大失联时间(down-after-milliseconds),如果sentinel在进行failover时发现slave失联,那么这个slave就会被sentinel认为不适合用来做新master的。
更严格的定义是,如果一个slave持续断开连接的时间超过
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
就会被认为失去选举资格。

符合上述条件的slave才会被列入master候选人列表,并根据以下顺序来进行排序:
1)sentinel首先会根据slaves的优先级来进行排序,优先级越小排名越靠前。
2)如果优先级相同,则查看复制的下标,哪个从master接收的复制数据多,哪个就靠前。
3)如果优先级和下标都相同,就选择进程ID较小的那个。

一个redis无论是master还是slave,都必须在配置中指定一个slave优先级。要注意到master也是有可能通过failover变成slave的。
如果一个redis的slave优先级配置为0,那么它将永远不会被选为master。但是它依然会从master哪里复制数据。

1.18 故障转移

所谓故障转移就是当master宕机,选一个合适的slave来晋升为master的操作,redis-sentinel会自动完成这个,不需要我们手动来实现。

一次故障转移操作大致分为以下流程:
发现主服务器已经进入客观下线状态。
对我们的当前集群进行自增, 并尝试在这个集群中当选。
如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选。 如果当选成功, 那么执行以下步骤:
选出一个从服务器,并将它升级为主服务器。
向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。
通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。
向已下线主服务器的从服务器发送 SLAVEOF 命令, 让它们去复制新的主服务器。
当所有从服务器都已经开始复制新的主服务器时, 领头 Sentinel 终止这次故障迁移操作。
每当一个 Redis 实例被重新配置(reconfigured) —— 无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 —— Sentinel 都会向被重新配置的实例发送一个 CONFIG REWRITE 命令, 从而确保这些配置会持久化在硬盘里。

Sentinel 使用以下规则来选择新的主服务器:
在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被淘汰。
在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被淘汰。
在经历了以上两轮淘汰之后剩下来的从服务器中, 我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器; 如果复制偏移量不可用, 或者从服务器的复制偏移量相同, 那么带有最小运行 ID 的那个从服务器成为新的主服务器。

Sentinel 自动故障迁移的一致性特质
Sentinel 自动故障迁移使用 Raft 算法来选举领头(leader) Sentinel , 从而确保在一个给定的纪元(epoch)里, 只有一个领头产生。

这表示在同一个纪元中, 不会有两个 Sentinel 同时被选中为领头, 并且各个 Sentinel 在同一个纪元中只会对一个领头进行投票。

更高的配置纪元总是优于较低的纪元, 因此每个 Sentinel 都会主动使用更新的纪元来代替自己的配置。

简单来说, 可以将 Sentinel 配置看作是一个带有版本号的状态。 一个状态会以最后写入者胜出(last-write-wins)的方式(也即是,最新的配置总是胜出)传播至所有其他 Sentinel 。

举个例子, 当出现网络分割(network partitions)时, 一个 Sentinel 可能会包含了较旧的配置, 而当这个 Sentinel 接到其他 Sentinel 发来的版本更新的配置时, Sentinel 就会对自己的配置进行更新。

如果要在网络分割出现的情况下仍然保持一致性, 那么应该使用 min-slaves-to-write 选项, 让主服务器在连接的从实例少于给定数量时停止执行写操作, 与此同时, 应该在每个运行 Redis 主服务器或从服务器的机器上运行 Redis Sentinel 进程。

Sentinel 状态的持久化
Sentinel 的状态会被持久化在 Sentinel 配置文件里面。每当 Sentinel 接收到一个新的配置, 或者当领头 Sentinel 为主服务器创建一个新的配置时, 这个配置会与配置纪元一起被保存到磁盘里面。这意味着停止和重启 Sentinel 进程都是安全的。

Sentinel 在非故障迁移的情况下对实例进行重新配置
即使没有自动故障迁移操作在进行, Sentinel 总会尝试将当前的配置设置到被监视的实例上面。 特别是:

根据当前的配置, 如果一个从服务器被宣告为主服务器, 那么它会代替原有的主服务器, 成为新的主服务器, 并且成为原有主服务器的所有从服务器的复制对象。
那些连接了错误主服务器的从服务器会被重新配置, 使得这些从服务器会去复制正确的主服务器。
不过, 在以上这些条件满足之后, Sentinel 在对实例进行重新配置之前仍然会等待一段足够长的时间, 确保可以接收到其他 Sentinel 发来的配置更新, 从而避免自身因为保存了过期的配置而对实例进行了不必要的重新配置。

总结来说,故障转移分为三个步骤:

1)从下线的主服务的所有从服务里面挑选一个从服务,将其转成主服务
sentinel状态数据结构中保存了主服务的所有从服务信息,领头sentinel按照如下的规则从从服务列表中挑选出新的主服务;
删除列表中处于下线状态的从服务;
删除最近5秒没有回复过领头sentinel info信息的从服务;
删除与已下线的主服务断开连接时间超过 down-after-milliseconds*10毫秒的从服务,这样就能保留从的数据比较新(没有过早的与主断开连接);
领头sentinel从剩下的从列表中选择优先级高的,如果优先级一样,选择偏移量最大的(偏移量大说明复制的数据比较新),如果偏移量一样,选择运行id最小的从服务。

2)已下线主服务的所有从服务改为复制新的主服务
挑选出新的主服务之后,领头sentinel 向原主服务的从服务发送 slaveof 新主服务 的命令,复制新master。

3)将已下线的主服务设置成新的主服务的从服务,当其回复正常时,复制新的主服务,变成新的主服务的从服务
同理,当已下线的服务重新上线时,sentinel会向其发送slaveof命令,让其成为新主的从。

温馨提示:还可以向任意sentinel发生sentinel failover 进行手动故障转移,这样就不需要经过上述主客观和选举的过程

二、Sentinel命令

2.1 登录sentinel 客户端

命令: redis-cli -h IP地址 -p 端口号

        例如:  redis-cli -h 127.0.0.1 -p 26379 

2.2 Sentinel 哨兵命令

PING :返回 PONG 。
SENTINEL masters :列出所有被监视的主服务器,以及这些主服务器的当前状态;
SENTINEL slaves  :列出给定主服务器的所有从服务器,以及这些从服务器的当前状态;
SENTINEL get-master-addr-by-name  : 返回给定名字的主服务器的 IP 地址和端口号。 如果这个主服务器正在执行故障转移操作, 或者针对这个主服务器的故障转移操作已经完成, 那么这个命令返回新的主服务器的 IP 地址和端口号;
SENTINEL reset  : 重置所有名字和给定模式 pattern 相匹配的主服务器。 pattern 参数是一个 Glob 风格的模式。 重置操作清楚主服务器目前的所有状态, 包括正在执行中的故障转移, 并移除目前已经发现和关联的, 主服务器的所有从服务器和 Sentinel ;
SENTINEL failover  : 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移。 (不过发起故障转移的 Sentinel 会向其他 Sentinel 发送一个新的配置,其他 Sentinel 会根据这个配置进行相应的更新)

SENTINEL MONITOR  这个命令告诉sentinel去监听一个新的master
SENTINEL REMOVE  命令sentinel放弃对某个master的监听
SENTINEL SET  这个命令很像Redis的CONFIG SET命令,用来改变指定master的配置。支持多个

2.3 命令简单示例

[root@localhost redis-5.0.5]# redis-cli -p 26379
127.0.0.1:26379> ping
PONG
127.0.0.1:26379> sentinel masters
1)  1) "name"
    2) "master-6379"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6379"
    7) "runid"
    8) "06a057ac0d6a39e4b80c2e56e3932b76862a219e"
    9) "flags"
   10) "master"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "430"
   19) "last-ping-reply"
   20) "430"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "683"
   25) "role-reported"
   26) "slave"
   27) "role-reported-time"
   28) "30815"
   29) "config-epoch"
   30) "2"
   31) "num-slaves"
   32) "2"
   33) "num-other-sentinels"
   34) "0"
   35) "quorum"
   36) "1"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
127.0.0.1:26379> sentinel get-master-addr-by-name master-6379
1) "127.0.0.1"
2) "6380"

三、Sentinel 哨兵模式配置

3.1 服务器列表

节点类型

IP地址

端口

配置文件

Master主节点

192.168.146.135

6379

redis-6379.conf

Slave1 从节点

192.168.146.135

6380

redis-6380.conf

Slave2 从节点

192.168.146.135

6381

redis-6381.conf

哨兵服务1

192.168.146.135

26379

sentinel-26379.conf

哨兵服务2

192.168.146.135

26380

sentinel-26380.conf

哨兵服务3

192.168.146.135

26381

sentinel-26381.conf

3.2 搭建主从模式

可以按照我的上一篇文章搭建主从复制模式,在一台Linux虚拟机上启动3台Redis进程,需要使用3个redis.conf配置文件,主要保证其 端口号、日志文件、pidfile 、dir 等配置不同

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第3张图片

3.3 sentinel.conf 配置文件详解

# Example sentinel.conf
 
# 哨兵sentinel实例运行的端口 默认26379
port 26379
 
# 哨兵sentinel的工作目录
dir /tmp
 
# 哨兵sentinel监控的redis主节点的 ip port 
# master-name  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor    
sentinel monitor mymaster 192.168.1.108 6379 2
 
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass  
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds  
sentinel down-after-milliseconds mymaster 30000
 
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
#这个数字越小,完成failover所需的时间就越长,
#但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
#可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs  
sentinel parallel-syncs mymaster 1
 
 
 
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面: 
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。  
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout  
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
 
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
#这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
#一个是事件的类型,
#一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script  
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
#       
# 目前总是“failover”,
# 是“leader”或者“observer”中的一个。 
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script  
 sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

3.3 搭建哨兵Sentinel模式

1)将 redis 安装包目录的sentinel.conf 配置文件复制3份到 conf 目录下,应用于3个Sentinle哨兵

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第4张图片

2) 配置文件修改

此处需要修改的核心配置项,主要3台的配置文件是不同的

#配置端口
port 26379
#以守护进程模式启动
daemonize yes
#日志文件名
logfile "/var/redis/logs/sentinel-26379.log"
#存放备份文件以及日志等文件的目录
dir "/var/redis/data"
#监控的IP 端口号 名称 sentinel通过投票后认为mater宕机的数量,此处为至少2个
sentinel monitor master-6379 127.0.0.1 6379 2
#Redis连接密码
sentinel auth-pass master-6379 123456
#30秒ping不同则认为宕机
sentinel down-after-milliseconds master-6379 30000
#故障转移后重新主从复制,1表示串行,>1并行
sentinel parallel-syncs master-6379 1
#故障转移开始,三分钟内没有完成,则认为转移失败
sentinel failover-timeout master-6379 180000

3) 启动哨兵模式

通过src目录下的 redis-sentinel 命令 和对应的配置文件启动,如果配置文件有错误,则会启动失败,并且提示哪一行的配置错误,可以根据提示进行修改,然后在启动

4)查看 sentinel 启动结果

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第5张图片

3.4 验证哨兵机制

1) 方法: 我们将 Master 关机模拟宕机情况,查看剩余的Slave 是否会选择出一个新的Master,这个主要当我们关机以后,需要稍等一会,因为哨兵巡察并且切换主机是需要一点时间的

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第6张图片

2) 日志查看

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第7张图片

9691:X 21 Feb 2021 23:40:23.238 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo  --Redis启动
9691:X 21 Feb 2021 23:40:23.238 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=9691, just started  --Redis状态
9691:X 21 Feb 2021 23:40:23.238 # Configuration loaded -- 配置加载成功
9692:X 21 Feb 2021 23:40:23.239 * Increased maximum number of open files to 10032 (it was originally set to 1024).
9692:X 21 Feb 2021 23:40:23.240 * Running mode=sentinel, port=26379. --哨兵运行端口号
9692:X 21 Feb 2021 23:40:23.240 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9692:X 21 Feb 2021 23:40:23.324 # Sentinel ID is d4c24c45edb70ef0bd422c9f3139233e5eb9d90d --哨兵ID
9692:X 21 Feb 2021 23:40:23.324 # +monitor master master-6379 127.0.0.1 6379 quorum 1 --添加哨兵监控的主节点
9692:X 21 Feb 2021 23:40:23.326 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master-6379 127.0.0.1 6379  --添加监控的从节点
9692:X 21 Feb 2021 23:40:23.329 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master-6379 127.0.0.1 6379  --添加监控的从节点
9692:X 21 Feb 2021 23:41:46.972 # +sdown master master-6379 127.0.0.1 6379 --主节点进行SDOWN状态
9692:X 21 Feb 2021 23:41:46.972 # +odown master master-6379 127.0.0.1 6379 #quorum 1/1  --投票成功,主节点确认宕机,进入ODOWN状态
9692:X 21 Feb 2021 23:41:46.972 # +new-epoch 1  --当前配置版本被更新时
9692:X 21 Feb 2021 23:41:46.972 # +try-failover master master-6379 127.0.0.1 6379  --达到failover条件,正等待其他sentinel的选举
9692:X 21 Feb 2021 23:41:46.974 # +vote-for-leader d4c24c45edb70ef0bd422c9f3139233e5eb9d90d 1  --投票这个节点宕机
9692:X 21 Feb 2021 23:41:46.974 # +elected-leader master master-6379 127.0.0.1 6379  --被选举为去执行failover的时候
9692:X 21 Feb 2021 23:41:46.974 # +failover-state-select-slave master master-6379 127.0.0.1 6379  --开始要选择一个slave当选新master时
9692:X 21 Feb 2021 23:41:47.036 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master-6379 127.0.0.1 6379  --找到了一个适合的slave来担当新master
9692:X 21 Feb 2021 23:41:47.037 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ master-6379 127.0.0.1 6379 --将6381执行SLAVEOF NO ONE 命令
9692:X 21 Feb 2021 23:41:47.089 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ master-6379 127.0.0.1 6379 --等待6381从机切换
9692:X 21 Feb 2021 23:41:47.581 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master-6379 127.0.0.1 6379 --宣布从机升级为主机
9692:X 21 Feb 2021 23:41:47.581 # +failover-state-reconf-slaves master master-6379 127.0.0.1 6379  --Failover状态变为reconf-slaves状态时
9692:X 21 Feb 2021 23:41:47.640 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ master-6379 127.0.0.1 6379 --sentinel发送SLAVEOF命令把它重新配置时
9692:X 21 Feb 2021 23:41:48.653 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ master-6379 127.0.0.1 6379  slave被重新配置为另外一个master的slave,但数据复制还未发生时
9692:X 21 Feb 2021 23:41:48.653 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ master-6379 127.0.0.1 6379 --slave被重新配置为另外一个master的slave并且数据复制已经与master同步时。
9692:X 21 Feb 2021 23:41:48.730 # +failover-end master master-6379 127.0.0.1 6379 --failover成功完成时
9692:X 21 Feb 2021 23:41:48.730 # +switch-master master-6379 127.0.0.1 6379 127.0.0.1 6381 --当master的地址发生变化时
9692:X 21 Feb 2021 23:41:48.731 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master-6379 127.0.0.1 6381
9692:X 21 Feb 2021 23:41:48.731 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ master-6379 127.0.0.1 6381
9692:X 21 Feb 2021 23:42:18.752 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ master-6379 127.0.0.1 6381

3)重启服务器 

当我们将服务器重启以后,这里需要稍等几秒钟,然后查看状态,发现其会自动以从机的身份加入到主从复制模式中

《Redis系列》第七章:高可用之哨兵模式(Sentinel)_第8张图片

3.5 发布与订阅消息

sentinel的日志文件里可以看到这些信息

客户端可以将 Sentinel 看作是一个只提供了订阅功能的 Redis 服务器: 你不可以使用 PUBLISH 命令向这个服务器发送信息, 但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通过订阅给定的频道来获取相应的事件提醒。

以下列出的是客户端可以通过订阅来获得的频道和信息的格式: 第一个英文单词是频道/事件的名字, 其余的是数据的格式。

如果这个redis实例是一个master,那么@之后的消息就不会显示。

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

你可能感兴趣的:(《你的Redis学会了吗》,redis)