Redis的哨兵

Redis-Sentinel简介

Redis Sentinel是一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每一个 Sentinel 节点会对数据节点和其他 Sentinel 节点进行监控,当它发现节点不可达时,会对节点作下线标识。若是被标识的是主节点,它还会和其余 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点不可达时,它们会选举出一个 Sentinel 节点来完成自动故障转移的工做(这个选举机制一会介绍),同时会将这个变化实时通知给 Redis 应用方。整个过程彻底是自动的,不须要人工来介入,因此这套方案颇有效地解决了 Redis高可用问题,能够理解为:以前的主从复制中增长了几个哨兵(这里注意是几个而不是一个)来监控redis,若是主机挂了,哨兵会通过选举在从机中选出一个redis做为主机,这样就没必要手动切换了。php

clipboard.png

Redis Sentinel 的功能

监控:Sentinel 节点会按期检测 Redis 数据节点、其他 Sentinel 节点是否可达。
通知:Sentinel 节点会将故障转移的结果通知给应用方。
主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。
配置提供者:在 Redis Sentinel 结构中,客户端在初始化的时候链接的是 Sentinel 节点集合,从中获取主节点信息。
同时Redis Sentinel 包含了若个 Sentinel 节点,这样作也带来了两个好处:
对于节点的故障判断是由多个 Sentinel 节点共同完成,这样能够有效地防止误判。
Sentinel 节点集合是由若干个 Sentinel 节点组成的,这样即便个别 Sentinel 节点不可用,整个 Sentinel 节点集合依然是健壮的。
Sentinel 节点自己就是独立的 Redis 节点,只不过它们有一些特殊,它们不存储数据,只支持部分命令node

基本的故障转移流程:

1.主节点出现故障,此时两个从节点与主节点失去链接,主从复制失败。
2.每一个Sentinel 节点经过按期监控发现主节点出现了故障。
3.多个 Sentinel 节点对主节点的故障达成一致会选举出其中一个节点做为领导者负责故障转移。
4.Sentinel 领导者节点执行了故障转移,整个过程基本是跟咱们手动调整一致的slaveof no one,只不过是自动化完成的。
5.故障转移后整个 Redis Sentinel 的结构,从新选举了新的主节点,而且会通知给客户端。redis

Sentinel 的配置

  1. sentinel monitor <master-name> <ip> <port> <count>

监控的主节点的名字IP端口,最后一个count的意思是有几台 Sentinel 发现有问题,就会发生故障转移,例如 配置为2,表明至少有2个 Sentinel 节点认为主节点不可达,那么这个不可达的断定才是客观的。对于设置的越小,那么达到下线的条件越宽松,反之越严格。通常建议将其设置为 Sentinel 节点的一半加1
注意:最后的参数不得大于conut(sentinel)缓存

  1. 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已经完成,将会显示被提高为masterslaveip和端口。
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 还不懂其原理。那么接下来就来看下 Sentinel 的实现原理,主要分为如下三个步骤。

1.检测问题之三个定时任务

10秒每一个 SentinelMasterSlave 执行一次 Info Replication
2秒每一个 Sentinel 经过 Master 节点的 channel 交换信息(pub/sub)。
1秒每一个 Sentinel 对其余 SentinelRedis 执行 ping
第一个定时任务,指的是 Redis Sentinel 能够对 Redis 节点作失败判断和故障转移,在 Redis 内部有三个定时任务做为基础,来 Info Replication 发现 Slave 节点,这个命令能够肯定主从关系。
第两个定时任务,相似于发布订阅,Sentinel 会对主从关系进行断定,经过 _sentinel_:hello 频道交互。了解主从关系能够帮助更好的自动化操做 Redis。而后 Sentinel 会告知系统消息给其它 Sentinel 节点,最终达到共识,同时 Sentinel 节点可以互相感知到对方。
第三个定时任务,指的是对每一个节点和其它 Sentinel 进行心跳检测,它是失败断定的依据。

2.发现问题之主观下线和客观下线

当有一台 Sentinel 机器发现问题时,它就会主观对它主观下线,可是当多个 Sentinel 都发现有问题的时候,才会出现客观下线。
咱们先来回顾一下 Sentinel 的配置。

sentinel monitor <master-name>  <ip> <port>   <count>

sentinel down-after-milliseconds <master-name> 30000

Sentinelping 每一个节点,若是超过30秒,依然没有回复的话,作下线的判断。

什么是主观下线呢?

每一个 Sentinel 节点对 Redis 节点失败的“偏见”。之因此是偏见,只是由于某一台机器30秒内没有获得回复。

如何作到客观下线?

这个时候须要全部 Sentinel 节点都发现它30秒内无回复,才会达到共识。

3.找到解决问题的人之领导者选举

1.每一个作主观下线的sentinel节点,会向其余的sentinel节点发送命令,要求将它设置成为领导者
2.收到命令sentinel节点,若是没有赞成经过其它节点发送的命令,那么就会赞成请求,不然就会拒绝
3.若是sentinel节点发现本身票数超过半数,同时也超过了sentinel monitor <master-name> <ip> <port> <count> 超过count个的时候,就会成为领导者

4.解决问题之故障转移

如何选择“合适的”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 nodemaster 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处理。

相关文章
相关标签/搜索