Redis Sentinel是一个分布式架构,其中包含若干个 Sentinel
节点和 Redis
数据节点,每一个 Sentinel
节点会对数据节点和其他 Sentinel
节点进行监控,当它发现节点不可达时,会对节点作下线标识。若是被标识的是主节点,它还会和其余 Sentinel
节点进行“协商”,当大多数 Sentinel
节点都认为主节点不可达时,它们会选举出一个 Sentinel
节点来完成自动故障转移的工做(这个选举机制一会介绍),同时会将这个变化实时通知给 Redis
应用方。整个过程彻底是自动的
,不须要人工来介入,因此这套方案颇有效地解决了 Redis
的高可用
问题,能够理解为:以前的主从复制中增长了几个哨兵(这里注意是几个而不是一个)来监控redis
,若是主机挂了,哨兵会通过选举在从机中选出一个redis
做为主机,这样就没必要手动切换了。php
1·
监控:Sentinel 节点会按期检测 Redis 数据节点、其他 Sentinel 节点是否可达。2·
通知:Sentinel 节点会将故障转移的结果通知给应用方。3·
主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。4·
配置提供者:在 Redis Sentinel
结构中,客户端在初始化的时候链接的是 Sentinel
节点集合,从中获取主节点信息。
同时Redis Sentinel
包含了若个 Sentinel
节点,这样作也带来了两个好处:5·
对于节点的故障判断是由多个 Sentinel
节点共同完成,这样能够有效地防止误判。6·
Sentinel 节点集合是由若干个 Sentinel
节点组成的,这样即便个别 Sentinel
节点不可用,整个 Sentinel
节点集合依然是健壮的。
Sentinel 节点自己就是独立的 Redis
节点,只不过它们有一些特殊,它们不存储数据,只支持部分命令node
1.主节点出现故障,此时两个从节点与主节点失去链接,主从复制失败。
2.每一个Sentinel
节点经过按期监控发现主节点出现了故障。
3.多个 Sentinel
节点对主节点的故障达成一致会选举出其中一个节点做为领导者负责故障转移。
4.Sentinel
领导者节点执行了故障转移,整个过程基本是跟咱们手动调整一致的slaveof no one
,只不过是自动化完成的。
5.故障转移后整个 Redis Sentinel
的结构,从新选举了新的主节点,而且会通知给客户端。redis
sentinel monitor <master-name> <ip> <port> <count>
监控的主节点的名字
、IP
和端口
,最后一个count
的意思是有几台 Sentinel 发现有问题,就会发生故障转移,例如 配置为2,表明至少有2个 Sentinel 节点认为主节点不可达,那么这个不可达的断定才是客观的。对于设置的越小,那么达到下线的条件越宽松,反之越严格。通常建议将其设置为 Sentinel 节点的一半加1
注意:最后的参数不得大于conut(sentinel)缓存
sentinel down-after-millseconds <master-name> 30000
这个是超时的时间(单位为毫秒)。打个比方,当你去 ping 一个机器的时候,多长时间后仍 ping 不通,那么就认为它是有问题
3.sentinel parallel-syncs <master-name> 1
当 Sentinel 节点集合对主节点故障断定达成一致时,Sentinel 领导者节点会作故障转移操做,选出新的主节点,原来的从节点会向新的主节点发起复制操做,parallel-syncs
就是用来限制在一次故障转移以后,每次向新的主节点发起复制操做的从节点个数,指出 Sentinel 属于并发
仍是串行
。1表明每次只能复制一个,能够减轻 Master 的压力;swoole
4.sentinel auth-pass <master-name> <password>
网络
若是 Sentinel
监控的主节点配置了密码,sentinel auth-pass
配置经过添加主节点的密码,防止 Sentinel
节点对主节点没法监控。
5.sentinel failover-timeout mymaster 180000
表示故障转移的时间。
6.sentinel支持的合法命令以下:SENTINEL masters
显示被监控的全部master
以及它们的状态.SENTINEL master <master name>
显示指定master
的信息和状态;SENTINEL slaves <master name>
显示指定master
的全部slave
以及它们的状态;SENTINEL get-master-addr-by-name <master name>
返回指定master的ip和端口,若是正在进行failover
或者failover
已经完成,将会显示被提高为master
的slave
的ip
和端口。SENTINEL failover <master name>
强制sentinel
执行failover
,而且不须要获得其余sentinel
的赞成。可是failover
后会将最新的配置发送给其余sentinel
。架构
修改配置sentinel monitor <master-name> <ip> <port> <count>
添加新的监听并发
SENTINEL REMOVE <master-name>
放弃对某个master监听异步
SENTINEL set failover-timeout <master-name> 180000
设置配置选项分布式
`Master`可能会由于某些状况宕机了,若是在客户端是固定一个地址去访问,确定是不合理的,因此客户端请求是请求哨兵,从哨兵获取主机地址的信息,或者是从机的信息。能够实现一个例子
一、随机选择一个哨兵链接,获取主机、从机信息
二、模拟客户端定时访问,实现简单轮训效果,轮训从节点
三、链接失败重试访问
这里我简单写个例子,这里我用了swoole
的定时器
<?php class Round{ static $lastIndex=0; public function select($list){ $currentIndex=self::$lastIndex; //当前的index $value=$list[$currentIndex]; if($currentIndex+1>count($list)-1){ self::$lastIndex=0; }else{ self::$lastIndex++; } return $value; } } $sentinelConf=[ ['ip'=>'xxx','port'=>xxx], ['ip'=>'xxx','port'=>xxx], ['ip'=>'xxx','port'=>xxx] ]; //随机访问 $sentinelInfo=$sentinelConf[array_rand($sentinelConf)]; $redis=new Redis(); $redis->connect($sentinelInfo['ip'],$sentinelInfo['port']); //rawCommand参数 1 command 2 arguments 3. $slavesInfo=$redis->rawCommand('SENTINEL','slaves','mymaster'); $slaves=[]; foreach ($slavesInfo as $val){ $slaves[]=['ip'=>$val[3],'port'=>$val[5]]; } //加载到缓存当中,能够记录此次访问的时间跟上次的访问时间 //模拟客户端访问 swoole_timer_tick(600,function () use($slaves) { //轮训 $slave=(new Round())->select($slaves); try{ $redis=new Redis(); $redis->connect($slave['ip'],$slave['port']); var_dump($slave,$redis->get('username')); }catch (\RedisException $e){ } });
说完了 Sentinel
的代码实现,不少人对 Sentinel
还不懂其原理。那么接下来就来看下 Sentinel
的实现原理,主要分为如下三个步骤。
每10
秒每一个 Sentinel
对 Master
和 Slave
执行一次 Info Replication
。
每2
秒每一个 Sentinel
经过 Master
节点的 channel
交换信息(pub/sub
)。
每1
秒每一个 Sentinel
对其余 Sentinel
和 Redis
执行 ping
。
第一个定时任务,指的是 Redis Sentinel
能够对 Redis
节点作失败判断和故障转移,在 Redis
内部有三个定时任务做为基础,来 Info Replication
发现 Slave
节点,这个命令能够肯定主从关系。
第两个定时任务,相似于发布订阅,Sentinel
会对主从关系进行断定,经过 _sentinel_:hello
频道交互。了解主从关系能够帮助更好的自动化操做 Redis
。而后 Sentinel
会告知系统消息给其它 Sentinel
节点,最终达到共识,同时 Sentinel
节点可以互相感知到对方。
第三个定时任务,指的是对每一个节点和其它 Sentinel
进行心跳检测,它是失败断定的依据。
当有一台 Sentinel
机器发现问题时,它就会主观对它主观下线,可是当多个 Sentinel
都发现有问题的时候,才会出现客观下线。
咱们先来回顾一下 Sentinel
的配置。
sentinel monitor <master-name> <ip> <port> <count> sentinel down-after-milliseconds <master-name> 30000
Sentinel
会 ping
每一个节点,若是超过30
秒,依然没有回复的话,作下线的判断。
每一个 Sentinel
节点对 Redis
节点失败的“偏见”。之因此是偏见,只是由于某一台机器30秒内没有获得回复。
这个时候须要全部 Sentinel
节点都发现它30
秒内无回复,才会达到共识。
1.每一个作主观下线的sentinel
节点,会向其余的sentinel
节点发送命令,要求将它设置成为领导者
2.收到命令sentinel
节点,若是没有赞成经过其它节点发送的命令,那么就会赞成请求,不然就会拒绝
3.若是sentinel
节点发现本身票数超过半数,同时也超过了sentinel monitor <master-name> <ip> <port> <count>
超过count
个的时候,就会成为领导者
如何选择“合适的”Slave
节点Redis
内部实际上是有一个优先级配置的,在配置文件中 slave-priority
,这个参数是 Salve 节点的优先级配置,若是存在则返回,若是不存在则继续。
当上面这个优先级不知足的时候,Redis
还会选择复制偏移量最大的 Slave
节点,若是存在则返回,若是不存在则继续。之因此选择偏移量最大,这是由于偏移量越小,和 Master
的数据越不接近,如今 Master
挂掉了,说明这个偏移量小的机器数据也可能存在问题,这就是为何要选偏移量最大的 Slave
的缘由。
若是发现偏移量都同样,这个时候 Redis
会默认选择 runid
最小的节点。
1.Sentinel
节点不该该部署在一台物理“机器”上。
这里特地强调物理机是由于一台物理机作成了若干虚拟机或者现今比较流行的容器,它们虽然有不一样的 IP 地址,但实际上它们都是同一台物理机,同一台物理机意味着若是这台机器有什么硬件故障,全部的虚拟机都会受到影响,为了实现 Sentinel 节点集合真正的高可用,请勿将 Sentinel
节点部署在同一台物理机器上。
2.部署至少三个且奇数
个的 Sentinel
节点。
3.个以上是经过增长 Sentinel
节点的个数提升对于故障断定的准确性,由于领导者选举须要至少一半加1个节点,奇数个节点能够在知足该条件的基础上节省一个节点。
哨兵集群在发现master node
挂掉后会进行故障转移,也就是启动其中一个slave node
为master node
。在这过程当中,可能会致使数据丢失的状况。
由于master->slave
的复制是异步,因此可能有部分还没来得及复制到slave就宕机了,此时这些部分数据就丢失了,这个我至今没找到解决的办法,但愿有人更正。
脑裂,也就是说,某个master
所在机器忽然脱离了正常的网络,跟其它slave
机器不能链接,可是实际上master
还运行着。
此时哨兵可能就会认为master
宕机了,而后开始选举,讲其它slave
切换成master
。这时候集群里就会有2个master
,也就是所谓的脑裂。
此时虽然某个slave
被切换成了master
,可是可能client
还没来得及切换成新的master
,还继续写向旧的master
的数据可能就丢失了。
所以旧master
再次恢复的时候,会被做为一个slave
挂到新的master
上去,本身的数据会被清空,从新重新的master
复制数据。
min-slaves-to-write 1 min-slaves-max-lag 10
要求至少有1个slave
,数据复制和同步的延迟不能超过10
秒
若是说一旦全部的slave
,数据复制和同步的延迟都超过了10
秒钟,那么这个时候,master
就不会再接收任何请求了
上面两个配置能够减小异步复制和脑裂致使的数据丢失
在异步复制的过程中,经过min-slaves-max-lag
这个配置,就能够确保的说,一旦slave
复制数据和ack
延迟时间太长,就认为可能master
宕机后损失的数据太多了,那么就拒绝写请求,这样就能够把master
宕机时因为部分数据未同步到slave致使的数据丢失下降到可控范围内
集群脑裂由于client
还没来得及切换成新的master
,还继续写向旧的master的数据可能就丢失了经过min-slaves-to-write
确保必须是有多少个从节点链接,而且延迟时间小于min-slaves-max-lag
多少秒。
对于client
来说,就须要作些处理,好比先将数据缓存到内存当中,而后过一段时间处理,或者链接失败,接收到错误切换新的master
处理。