多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
`Sentinel`服务本身也是一个特殊的`Redis`服务,在`Redis`的安装包内,除了`redis.conf`文件,还有一个`sentinel.conf`文件,这个就是启动`sentinel`服务的配置文件。 启动`Sentinel`服务的命令通过`redis-sentinel`来执行(如:`./redis-sentinel ../sentinel.conf`)或者也可以通过`redis-server`命令指定参数`sentinel`来启动(如:`./redis-server ../sentinel.conf --sentinel`)。 `Sentinel`主要用来监控`Redis`集群中的所有节点,当`Sentinel`服务发现`master`不可用时,可以从所有可用的`slave`节点中选出一个新的节点升级为`master`,从而实现`master`服务的自动切换。 如果`Sentinel`服务自己挂了怎么办?为了实现高可用,`Sentinel`服务本身也是一个集群。和`master-slave`模式不同的是,`Sentinel`集群之间在正常情况下没有主从关系,相互之间是平等的,只有在需要执行故障转移时才需要进行`Leader`选举。 下图所示就是一个`3`节点`Sentinel`服务集群和`1`主`2`从的`Redis Sentinel`集群示意图: ![](https://img.kancloud.cn/a1/4b/a14bf480f86e28ab63a08c9f2ff46f77_608x351.png) `Sentinel`集群之间的服务会互相监控,然后每个`Sentinel`服务都会监控所有的`master`和`slave`节点,一旦发现`master`节点不可用,则`Sentinel`集群会通过选举产生`Leader`,再由`Leader`节点执行故障转移,切换`master`节点。 #### 主观下线和客观下线 `Sentinel`服务默认以每秒`1`次的频率向`Redis`服务节点发送`ping`命令(`Sentinel`服务之间也会发送`ping`命令进行检测)。如果在指定时间内(由参数`down-after-milliseconds`进行控制,默认`30s`)没有收到有效回复,则`Sentinel`会将该服务器标记为下线,称之为:**主观下线**。 ~~~ down-after-milliseconds master-name milliseconds #判断主观下线超时时间 ~~~ 当某一个`Sentinel`服务把`master`节点标记为主观下线之后,会去询问其它`Sentinel`服务,确认这个`master`是否真的下线,当达到指定数量的`Sentinel`服务都认为当前`master`节点已经主观下线,这时候首先发现`master`节点主观下线的`Sentinel`服务就会将`master`节点标记为**客观下线**,并发起`Leader`选举,最后由`Leader`执行**故障转移**操作。 多少个`Sentinel`服务认定`master`节点“主观下线”才会正式将`master`节点标记为“客观下线”由以下参数控制: ~~~ sentinel monitor <master-name> <ip> <redis-port> <quorum> #quorum 选项就是决定判断客观下线的条数 ~~~ 需要注意的是,每个`Sentinel`服务判断主观下线和客观下线的配置可能不一样,所以当某一个`Sentinel`服务判定`master`已经主观下线或者客观下线时,其它`Sentinel`服务并不一定会这么认为,但是只要有一个`Sentinel`判定`master`已经客观下线,`Sentinel`就会准备执行故障转移。在执行故障转移之前,`Sentinel`服务之间必须进行`Leader`选举。 #### Leader 选举 当某一个或者多个`Sentinel`服务判定`master`服务已经下线,`Sentinel`服务就会发起`Leader`选举,选举出`Leader`之后,由`Leader`节点执行故障转移。 ##### Raft 选举算法 `Sentinel`服务的`Leader`选举是通过`Raft`算法来实现的。`Raft`是一个共识算法(consensus algorithm),其核心思想主要有两点: * 先到先得 * 少数服从多数 在`Raft`算法中,每个节点都维护了一个属性`election timeout`,这是一个随机的时间,范围在`150ms~300ms`之间,哪个节点先到达这个时间,哪个节点就可以发起选举投票。 选举过程可以总结为以下步骤: 1. 发起选举的服务首先会给自己投上一票。 2. 然后发起选举的节点会向其它节点发送投票请求,其它节点在收到请求后如果在同一个`election timeout`范围内还没有投过票,那么就会给发起选举的节点投上一票,然后将`election timeout`重置(一个`election timeout`区间只能发起一次投票)。 3. 如果发起选举的节点获得的票数超过一半,那么当前服务就会成为`Leader`节点,成为`Leader`节点之后就会维护一个`heartbeat timeout`时间属性(即:心跳间隔时间),在每一次到达`heartbeat timeout`时间时,`Leader`节点就会向其它`Follow`节点发起一个心跳检测。 4. `Follow`节点收到`Leader`节点的心跳包之后就会将`election timeout`清空,这样可以防止`Follow`节点因为到达`election timeout`而发起选举。 5. 假如`Leader`节点挂了,那么`Follow`节点的`election timeout`将不会被清空,谁先到达,谁就会再次发起选举。 PS:因为`election timeout`是一个随机值,虽然概率小,但也可能出现两个节点同时发起投票选举,这种情况就可能出现一次选举并不能选出`Leader`(比如总共`4`个节点,每个节点都得了`2`票),此时就会等待下一次首先到达`election timeout`的节点再次发起投票选举。 如果对`Raft`算法感兴趣的,可以[点击这里](http://thesecretlivesofdata.com/raft/)观看演示。 ##### Sentinel 选举 Leader `Sentinel`中的选举算法虽然是源于`Raft`算法,但是也做了以下改进: 1. 触发选举并不是由`election timeout`时间决定,而是由谁先判定`master`下线来决定的。 2. `Sentinel`节点并没有维护`election timeout`属性,而是维护了一个配置纪元`configuration epoch`属性,配置纪元是一个计数器(默认`0`),每一个`Sentinel`节点的同一个配置纪元只能投票`1`次(先到先得),每次投票前会将配置纪元自增`1`。 3. 选举出`Leader`之后,`Leader`并不会通知其它`Follow`节点自己成为了`Leader`。当`Leader`节点选出新的`master`,其它`Sentinel`服务检测到新的`master`上线之后,就会删除自己的主观下线标记。 #### 故障转移 当`Sentinel`选举出`Leader`之后,`Leader`就会开始执行故障转移,执行故障转移主要分为以下三步: 1. 在已判定客观下线的`master`服务器的`slave`服务器列表中找到一个合格的`slave`服务器,向其发送`replicaof no one`命令,使其转换为`master`角色。 2. 向其它从服务器发送`replicaof ip port`命令(`ip`和`port`为新`master`地址),使其成为新`master`服务的`slave`节点。 3. 将已下线的`master`服务也设置为新的`master`服务的`slave`节点,这样当旧`master`恢复之后能以`slave`的角色继续运行。 ##### 如何选举新的 master 节点 新的`master`选举条件主要参考`4`个因素: 1. 断开连接时长:首先将所有于已下线`master`节点断开连接时间超过`down-after-milliseconds * 10`的`slave`节点删除掉,确保`slave`节点的数据都是比较新的。 2. `slave`节点的优先级排序:将所有的`slave`节点按照优先级进行排序,选出优先级最高的`slave`节点作为新的`master`节点(优先级由配置文件参数`replica-priority`决定,默认`100`)。 3. 复制偏移量:如果有多个优先级相同的`slave`节点,则选出复制偏移量最大的`slave`节点。 4. 进程`id`:如果还是没选出新的`master`节点,那么会再次选择进程`id`最小的`slave`节点作为新的`master`节点。