• Redis—听说你速度跟甲斗一样快?——哨兵


    前言

    我们接着前文
    现在你使用了Redis主从复制架构,这大大提升了你业务的稳定性和高效性
    主从复制架构
    master对外提供服务,salve去同步master的数据,这样如果master发生宕机,我们可以手动把slave提升为master继续提供服务;还有一点是slave可以提供读服务,分担一部分读请求,这样可以减轻master的负担,提升整体的性能

    这个架构看起来不错,那么它有什么不足之处吗?

    这个架构的问题在于:当master出现宕机时,我们需要手动地把slave提升为master,这个人工干预的过程是需要花费时间的,在这个期间你的业务还是很有可能收到影响

    那我们是否可以把这个过程交给机器来做,不需要人工干预,使其变成一个自动化过程

    我们需要设置一个故障自动切换机制,将slave提升为master这个过程交给机器来做,于是便有了Redis的第二个架构——哨兵机制

    工作原理

    • 每个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着
    • 如果发现对方在 指定时间( down-after-milliseconds项 )内未回应,则暂时认为对方已挂(主观宕机: sdown)
    • 若“哨兵群“中的多数 sentinel,都报告某一master没响应,系统才认为该master”彻底死
      亡”(客观上的真正down机: odown),通过一定的 vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置
      在这里插入图片描述
    #主观宕机(SDOWN)
    	即单个sentinel认为某个服务下线(有可能是接收不到订阅,网络不通等)
    	主观下线就是说如果服务器在down-after-milliseconds给定的毫秒数之内,没有返回Sentinel 发送的 PING 命令的回复,或者返回一个错误,那么 Sentinel 将这个服务器标记为主观下线(SDOWN)
    
    #客观宕机(ODOWN)
    	多个sentinel实例对同一台服务器做出SDOWN判断,并且通过SENTINEL is-master-down-by-addr 命令互相交流之后,得出的服务器下线判断,然后开启failover。
    	客观下线就是说只有在足够数量(quorum)的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(ODOWN),当sentinel监视的某个服务主观下线后,sentinel会询问其它监视该服务的sentinel,看它们是否也认为该服务主观下线,之后再进行故障迁移。
    	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接收到回复后,根据配置设置的下线最小数量,达到这个值,既认为该服务客观下线。客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所有从服务器或者其他 Sentinel 永远不会达到客观下线条件。只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.sentinel 工作过程

    1.每个sentinel向master、slave以及其他sentinel发送一个ping(1s一次)

    2.每个sentinel向master的pub/sub频道道__sentinel__收发hello(包含sentinel ip:port及配置版本信息,所有sentinel通过这种方式达成共识)消息(两秒一次)

    3.如果一个实例距离最后一次有效回复ping命令的时间超过down-after-milliseconds ,则这个实例会被Sentinel标记为主观下线

    4.当有足够数量的sentinel(大于等于quorum)在指定的时间范围内确认master的确进入了主观下线状态,则master会被标记为客观下线

    5.每个Sentinel 向所有Master,Slave发送 INFO 命令(正常十秒一次,标记客观下线后一秒一次)

    6.若没有足够数量的Sentinel同意Master已经下线,或者若Master重新向Sentinel 的PING命令返回有效回复,Master的主观下线状态就会被移除
    7.进行故障切换

    8.维护sentinel配置版本及持久化sentinel节点及集群主从关系等信息到sentinel.conf

    9.向外部客户端提供有效的redis-master连接信息(在故障切换后会更新)

    2.leader选举

    只能有一个sentinel能指挥完成整个集群的failover,所以当master客观下线时,需要进行sentinel leader选举
    1.所有的sentinel都有公平被选举成领头的资格(前提未配置sentinel can-failover mymasterno,默认是yes)

    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)redis集群需要开启外部网络访问,生产不能只侦听环回地址(伪集群测试无所谓了)
    2)sentinel节点数量推荐是>=3个的奇数,quorum生效的前提是>=ceil(sentinel节点数量/2)
    3)新增sentinel节点时请勿拷贝其它包含动态生成配置的sentinel配置文件
    
    • 1
    • 2
    • 3
    • 4

    3.节点之间如何发现

    我们发现sentinel配置文件里只配置了master的地址信息(host和port),并没有配置从节点以及其他哨兵节点的信息,但是我们在哨兵节点和主节点客户端通过info replicationinfo sentinel命令却能够发现它们,这是由哨兵的自动发现机制实现的

    • 数据节点

    一般情况下,哨兵节点每隔10秒(failover时每隔1秒)向主从节点发送info命令,以此获取主从节点的信息

    首次执行时只知道给出的主节点信息,通过对主节点执行info命令就可以获取其从节点列表,如此周期执行,就可以不断发现新的节点

    1.如果INFO命令目标是从节点:哨兵从返回信息中获取从节点所属的最新主节点ip和port,如果与历史记录不一致,则执行更新;获取从节点的优先级、复制偏移量以及与主节点的链接状态并更新。
    
    2.如果INFO命令目标是主节点:哨兵从返回信息中获取主节点的从机列表,如果从节点是新增的,则将其加入监控列表。
    
    3.无论目标是主节点还是从节点,都会记录其runId。
    
    4.如果节点的角色发生变化,哨兵会记录节点新的角色及上报时间。若此时哨兵运行在TILT模式下,则什么都不做。否则,会执行主从切换相关的逻辑,我们后面再细说
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 哨兵节点

    为了相互检查可用性及信息交互,哨兵之间是一直保持连接的,但是我们并没有配置告知它们彼此的存在,它们之间是怎么发现对方并交互的呢?

    我们知道哨兵通过INFO命令发现了主节点及从节点的地址信息,而redis提供了一种发布订阅的消息通信模式,PUB/SUB。

    哨兵们就是通过这一个约好的通道发布/订阅hello信息进行通信

    每隔2秒,每个哨兵会通过它所监控的主节点、从节点向__sentinel__:hello通道发布一条hello消息。
    每个哨兵会通过它所监控的主节点、从节点订阅__sentinel__:hello通道的消息,以此接收其他哨兵发布的信息
    
    • 1
    • 2
    每个哨兵都会维护其监控的主节点信息,如果它接收到其他哨兵消息后,发现自己维护的信息已经过时,则立即执行更行过程。
    
    如果哨兵接受到的信息没有在已有的监控列表中,就意味着发现了一个新的哨兵实例,此时会创建一个新的哨兵实例加入监控列表。在处理新增哨兵实例时,如果它与已存在的哨兵实例runId或者ip、port一致,将只保存最新的实例信息
    
    • 1
    • 2
    • 3

    哨兵部署

    1.相关命令

    redis-cli -h <IP> -p <PORT> info sentinel 
    # 查看sentinel的整体信息
    
    redis-cli -h <IP> -p <PORT> sentinel masters 
    # 查看sentinel监控的所有redis-master信息
    
    redis-cli -h <IP> -p <PORT> sentinel slaves testmaster 
    # 查看sentinel监控的testmaster集群中redis-slave信息
    
    redis-cli -h <IP> -p <PORT> sentinel get-master-addr-by-name testmaster 
    # 获取testmaster组中的master ip和端口
    
    redis-cli -h <IP> -p <PORT> sentinel reset pattern 
    # 重置所有名字和给定模式pattern 相匹配的主服务器。pattern 参数是一个Glob 风格的模式
    
    redis-cli -h <IP> -p 26379sentinel failover testmaster 
    # 强制对testmaster进行failover
    
    redis-cli -h <IP> -p <PORT> sentinel monitor <NAME> <IP> <PORT> <QUORUM> 
    # 动态新增sentinel监控的redis集群
    
    redis-cli -h <IP> -p <PORT> sentinel remove <NAME> 
    # 动态删除sentinel监控的redis集群
    
    redis-cli -h <IP> -p <PORT> sentinel <NAME> <OPTION> <VALUE> 
    # 动态新增sentinel监控集群的配置,类似redis的CONFIG SET命令
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.配置字段说明

    sentinel monitor mymaster 192.168.149.128 6379 2
    #当前Sentinel节点监控 192.168.149.128 6379 这个主节点
    #2代表判断主节点失败至少需要2个Sentinel节点节点同意
    #mymaster是redis监控主节点的别名
    
    sentinel down-after-milliseconds mymaster 10000
    #每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过10000毫秒且没有回复,则判定不可达
    
    sentinel parallel-syncs mymaster 1
    #当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起同步操作,限制每次向新的主节点发起同步操作的从节点个数为1
    
    sentinel failover-timeout mymaster 30000
    #故障转移超时时间为30000毫秒
    
    sentinel auth-pass 
    #如果Sentinel监控的主节点配置了密码,可以通过sentinel auth-pass配置通过添加主节点的密码,防止Sentinel节点无法对主节点进行监控
    #例如:sentinel auth-pass mymaster 88888888
    
    sentinel notification-script
    #在故障转移期间,当一些警告级别的Sentinel事件发生(指重要事件,如主观下线,客观下线等)时,会触发对应路径的脚本,想脚本发送相应的事件参数
    #例如:sentinel notification-script mymaster /var/redis/notify.sh
    
    sentinel client-reconfig-script
    #在故障转移结束后,触发应对路径的脚本,并向脚本发送故障转移结果的参数。
    #例如:sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    • master配置
    [root@master ~]# vim /etc/redis/redis-sentinel.conf
    bind0.0.0.0
    port 26379
    pidfile /var/redis/sentinel.pid
    dir /var/lib/redis
    daemonize yes
    protected-mode no
    logfile /var/log/redis/sentinel.log
    sentinel monitor mymaster 192.168.149.128 6379 2
    sentinel down-after-milliseconds mymaster 10000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 30000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    [root@master ~]# systemctl restart redis-sentinel
    
    • 1
    • slave1配置
    [root@slave1 ~]# vim /etc/redis/redis-sentinel.conf
    bind0.0.0.0
    port 26379
    daemonize yes
    protected-mode no
    dir /var/lib/redis
    logfile /var/log/redis/sentinel.log
    pidfile /var/redis/sentinel.pid
    sentinel monitor mymaster 192.168.149.128 6379 2
    sentinel down-after-milliseconds mymaster 10000
    sentinel failover-timeout mymaster 30000
    sentinel parallel-syncs mymaster 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    [root@slave1 ~]# systemctl restart redis-sentinel
    
    • 1
    • slave2配置
    [root@slave2 ~]# vim /etc/redis/redis-sentinel.conf
    bind0.0.0.0
    port 26379
    daemonize yes
    protected-mode no
    dir /var/lib/redis
    logfile /var/log/redis/sentinel.log
    pidfile /var/redis/sentinel.pid
    sentinel monitor mymaster 192.168.149.128 6379 2
    sentinel down-after-milliseconds mymaster 10000
    sentinel failover-timeout mymaster 30000
    sentinel parallel-syncs mymaster 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    [root@slave2 ~]# systemctl restart redis-sentinel
    
    • 1

    验证

    • master节点上执,如下操作,演示通过sentinel 进行故障转移和新master的选出
    [root@master ~]# systemctl stop redis
    
    • 1
    • 我们观看129节点上的sentinel日志
    [root@salve1 ~]# tailf /var/log/redis/sentinel.log
    
    • 1

    在这里插入图片描述

    可以看到已经成功将mater切换到 130这台节点上

  • 相关阅读:
    【云原生网关】Kong 使用详解
    【深度学习实验】注意力机制(二):掩码Softmax 操作
    亚马逊电动移动设备法规、标准和要求准则!!!
    STM32单片机DS18B20测温液晶1602显示例程(Proteus仿真+程序)
    Real-Time Rendering——8.2.3 Color Grading颜色分级
    夏天给宝宝开空调需要注意的几点
    二叉树的遍历方式和代码
    transform + asm资料
    站点信息搜集
    vue axios请求两种方式,出现401错误,需要添加config配置
  • 原文地址:https://blog.csdn.net/s_alted/article/details/126412052