redis的主从监控器—Sentinel

Redis-Sentinel简介

Redis Sentinel是一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点不可达时,它们会选举出一个 Sentinel 节点来完成自动故障转移的工作(这个选举机制一会介绍),同时会将这个变化实时通知给 Redis 应用方。整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了 Redis 的高可用问题,可以理解为:之前的主从复制中增加了几个哨兵(为什么会是几个而不是一个后面会写)来监控redis,如果主机挂了,哨兵会经过选举在从机中选出一个redis作为主机,这样就不必手动切换了,但是这个还是有弊端的后面会写出来。
先画个图方便理解。
在这里插入图片描述

为什么要使用Sentinel

上篇文章写过 Redis 复制的主要内容,但 Redis 复制有一个缺点,当主机 Master 宕机以后,我们需要人工解决切换,比如使用slaveof no one 。实际上主从复制并没有实现,高可用, 高可用侧重备份机器, 利用集群中系统的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务
如果我们有一个监控程序能够监控各个机器的状态及时作出调整,将手动的操作变成自动的。Sentinel的出现就是为了解决这个问题。

基本的故障转移流程:

1.主节点出现故障,此时两个从节点与主节点失去连接,主从复制失败。
在这里插入图片描述
2.每个 Sentinel 节点通过定期监控发现主节点出现了故障,这里是注意:每个,不是一个,这个后续会讲
在这里插入图片描述
3.多个 Sentinel 节点对主节点的故障达成一致会选举出其中一个节点作为领导者负责故障转移。
4.Sentinel 领导者节点执行了故障转移,整个过程基本是跟我们手动调整一致的slaveof no one,只不过是自动化完成的。
在这里插入图片描述
5)故障转移后整个 Redis Sentinel 的结构,重新选举了新的主节点,并且会通知给客户端
在这里插入图片描述

Redis Sentinel 的功能

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

Sentinel 的配置

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

监控的主节点的名字IP端口,最后一个count的意思是有几台 Sentinel 发现有问题,就会发生故障转移,例如 配置为2,代表至少有2个 Sentinel 节点认为主节点不可达,那么这个不可达的判定才是客观的。对于设置的越小,那么达到下线的条件越宽松,反之越严格。一般建议将其设置为 Sentinel 节点的一半加1
注意:最后的参数不得大于conut(sentinel)
2. sentinel down-after-millseconds <master-name> 30000
这个是超时的时间(单位为毫秒)。打个比方,当你去 ping 一个机器的时候,多长时间后仍 ping 不通,那么就认为它是有问题
3.sentinel parallel-syncs <master-name> 1
当 Sentinel 节点集合对主节点故障判定达成一致时,Sentinel 领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs 就是用来限制在一次故障转移之后,每次向新的主节点发起复制操作的从节点个数,指出 Sentinel 属于并发还是串行。1代表每次只能复制一个,可以减轻 Master 的压力;

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可能会因为某些情况宕机了,如果在客户端是固定一个地址去访问,肯定是不合理的,所以客户端请求是请求哨兵,从哨兵获取主机地址的信息,或者是从机的信息。可以实现一个例子
1、随机选择一个哨兵连接,获取主机、从机信息
2、模拟客户端定时访问,实现简单轮训效果,轮训从节点
3、连接失败重试访问
这里我简单写个例子,这里我用了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秒每个 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 进行心跳检测,它是失败判定的依据。

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

当有一台 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秒内无回复,才会达到共识。

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 node为master node。在这过程中,可能会导致数据丢失的情况。

1、异步复制导致数据丢失

因为master->slave的复制是异步,所以可能有部分还没来得及复制到slave就宕机了,此时这些部分数据就丢失了,这个我至今没找到解决的办法,希望有人更正。

2、集群脑裂导致数据丢失

脑裂,也就是说,某个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就不会再接收任何请求了

上面两个配置可以减少异步复制和脑裂导致的数据丢失

1、异步复制导致的数据丢失

在异步复制的过程当中,通过min-slaves-max-lag这个配置,就可以确保的说,一旦slave复制数据和ack延迟时间太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样就可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低到可控范围内

2、集群脑裂导致的数据丢失

集群脑裂因为client还没来得及切换成新的master,还继续写向旧的master的数据可能就丢失了通过min-slaves-to-write 确保必须是有多少个从节点连接,并且延迟时间小于min-slaves-max-lag多少秒。

客户端需要怎么做

对于client来讲,就需要做些处理,比如先将数据缓存到内存当中,然后过一段时间处理,或者连接失败,接收到错误切换新的master处理。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis 主从哨兵集群是一种高可用的解决方案,它使用哨兵(Sentinel)来监控和管理主从节点。哨兵会自动检测并切换故障的主节点,保证服务的连续性。以下是在 shell 中部署 Redis 主从哨兵集群的基本步骤: 1. **安装 RedisSentinel**: - 首先,确保你的系统已经安装了 Redis,如果没有,可以使用包管理器(如 apt-get 或 yum)安装。 - 安装 Sentinel,一般可以通过 Redis 的官方发行版或单独下载源码编译安装。 2. **配置 Sentinel**: - 在每个 Sentinel 服务器上编辑 `sentinel.conf` 文件,设置监听地址、集群名、哨兵角色等配置。例如: ``` sentinel monitor mycluster master 26379 2 10 ``` 这里 `mycluster` 是集群名称,`master` 是主节点的角色,`26379` 是主节点的端口,`2` 是当有多于两个 Sentinel 观察到主节点失败时的投票数,`10` 是在主节点失败后等待其他 Sentinel 同意切换的时间(秒)。 3. **配置主从节点**: - 对于主节点,设置 `protected-mode no`,允许外部客户端连接。 - 对于从节点,配置 `slaveof` 指令指向主节点,如: ``` redis-server --slaveof <master_ip> <master_port> ``` 4. **启动 RedisSentinel**: - 以守护进程模式启动 Redis 服务器,并指定 `sentinel` 插件,例如: ``` redis-server --sentinel <your_server_ip>:26379 ``` - 同样启动 Sentinel,监听不同的端口,如 `redis-server --sentinel` 5. **验证集群健康**: - 使用 Redis 命令行客户端 `redis-cli` 或者 `sentinel get-master-addr-by-name mycluster` 来检查哨兵是否能获取到正确的主节点地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值