上一篇说的Redis主从模式,切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式,自动切换,无需自己动手。

概述

Redis Sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他Sentinel节点进行“协商”,当大多数Sentinel节点都认为主节点不可达时,它们会选举出一个Sentinel节点来完成自动故障转移的工作,同时会将这个变化实时通知给Redis应用方。

整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了Redis的高可用问题。

哨兵模式是一种特殊的模式,哨兵模式是基于主从模式,Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
Redis哨兵(Sentinel)模式 - 图1

哨兵的三个作用:

  • 监控:监控谁?支持主从结构的工作一个是主节点一个是从节点,那肯定就是监控这俩个了。监控主节点和从节点是否正常运行;检测主节点是否存活,主节点和从节点运行情况。
  • 通知:哨兵检测的服务器出现问题时,会向其他的哨兵发送通知,哨兵之间就相当于一个微信群,每个哨兵发现的问题都会发在这个群里。
  • 自动转移故障:当检测到主节点宕机后,断开与宕机主节点连接的所有从节点,在从节点中选取一个作为主节点,然后将其他的从节点连接到这个最新主节点的上。并且告知客户端最新的服务器地址。

这里有一个注意点,哨兵也是一台 Redis 服务器,只是不对外提供任何服务。配置哨兵时配置为单数。

图解

哨兵系统监控了一主三从。
Redis哨兵(Sentinel)模式 - 图2
此时主服务器掉线
Redis哨兵(Sentinel)模式 - 图3
从服务server2被升级为新的主服务,server3和server3设置server2为主服务,进行复制数据和提供服务。
Redis哨兵(Sentinel)模式 - 图4

优点

解决了单点网络故障问题和自动故障转移。

缺点

依然无法解决单个节点的性能压力

哨兵sentinel初始化的过程

  1. 初始化服务器(sentinel也是一个正常的redis服务器)
  2. 将普通的redis使用的代码替换为哨兵sentinel专用代码
    1. 不用RDB/AOF文件(因为不需要加载数据,他为监控节点,而不是数据节点)
    2. 端口号不一样(sentinel的端口号为26379,而默认的redis端口为6379)
    3. 普通redis命令:set/get/dbsize
    4. 哨兵命令:ping/sentinel
  3. 初始化哨兵状态 sentinel
  4. 向redis服务器创建连接
    1. 一个命令连接:向主服务器发送命令,并接受回复
    2. 一个订阅连接:sentinel:hello频道
    3. 在发送与订阅功能中,被发送的消息不会保存在服务器中。当客户端不在线/断线中,为了不丢失这条消息,redis就用了一个订阅频道来接受这条消息。

      哨兵如何监控?

      Redis哨兵(Sentinel)模式 - 图5
      检测实例是否下线:
      主观下线:sentinel与服务器断开时间超过指定时间
      客观下线:客观下线数量超过半数

监控流程:

  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
  5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
  6. 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
  7. 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
  8. 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

    Sentinel为什么是3个?

    首先必须哨兵节点必须客观的认为redis节点下线才可以进行主从切换,也就是说,需要多数的哨兵都主观的认为redis主节点下线,为什么呢?如果redis节点正常服务而哨兵服务网络波动而主观认定redis主节点下线,这样是无法进行主从切换的,这样可以有效地防止误判。
    哨兵集群必须部署两个以上节点,如果哨兵集群仅仅部署了两个哨兵实例,那么他的大多数为2(2的大多数为2,3的大多数为2,5的大多数为3,4的大多数为2),如果其中一个哨兵宕机,就无法满足大多数大于等于2,那么在master发生故障的时候就无法进行主从切换。

    故障转移流程

  9. sentinel领导节点的选举

Leader只是故障转移中出现的角色
采用Raft算法。

  1. redis主节点的选举

由领导节点将所有的从服务器保存在列表中,然后一项项过滤
A.去除所有处于下线的
B.去除近5s内没有回复的
C.优先级+复制偏移量最大(要求数据为最新的)
D.排序,选择运行ID最小的。

环境搭建

在上一篇Redis主从模式的基础上,我们再搭建三个哨兵节点。

复制配置文件

哨兵使用的配置文件是 sentinel.conf

  1. [root@redis-master redis-6.2.4]# cp sentinel.conf sentinel-1.conf
  2. [root@redis-master redis-6.2.4]# cp sentinel.conf sentinel-2.conf
  3. [root@redis-master redis-6.2.4]# cp sentinel.conf sentinel-3.conf

修改哨兵节点配置文件

三个哨兵的端口分别为26379,26380,26381。

  1. [root@redis-master redis-6.2.4]# vim sentinel-1.conf
  2. port 26379
  3. sentinel monitor mymaster 127.0.0.1 6381 2
  4. sentinel auth-pass mymaster anin
  5. # 在测试阶段可以设置为no,方便看日志
  6. daemonize yes
  7. sentinel down-after-milliseconds mymaster 5000
  8. sentinel parallel-syncs mymaster 1
  9. sentinel failover-timeout mymaster 15000
  • port:当前sentinel服务运行的端口。
  • sentinel monitor mymaster 127.0.0.1 6379 2:sentinel监视一个叫mymaster的主redis实例,这个主实例的IP地址为127.0.0.1,端口号为6379,后边的 2 代表的是,如果有俩个哨兵判断这个主节点挂了那这个主节点就挂了,通常设置为哨兵个数一半加一。
  • sentinel auth-pass mymaster:redis的主节点配置的认证密码
  • daemonize**:**后台启动,在测试阶段可以设置为no,方便看日志
  • sentinel down-after-milliseconds mymaster 5000:自动失效时间,单位是毫秒。
  • sentinel parallel-syncs mymaster 1:为指定执行故障转移的时候,最多可以有什么个从redis实例在同步新的主实例。
  • sentinel failover-timeout mymaster 15000:为如果在该时间内未完成节点切换,则认为失败。
    1. [root@redis-master redis-6.2.4]# vim sentinel-2.conf
    2. port 26380
    3. sentinel monitor mymaster 127.0.0.1 6381 2
    4. sentinel auth-pass mymaster anin
    5. sentinel down-after-milliseconds mymaster 5000
    6. sentinel parallel-syncs mymaster 1
    7. sentinel failover-timeout mymaster 15000
    1. [root@redis-master redis-6.2.4]# vim sentinel-3.conf
    2. port 26381
    3. sentinel monitor mymaster 127.0.0.1 6381 2
    4. sentinel auth-pass mymaster anin
    5. sentinel down-after-milliseconds mymaster 5000
    6. sentinel parallel-syncs mymaster 1
    7. sentinel failover-timeout mymaster 15000

    启动哨兵节点

    1. [root@redis-master src]# redis-sentinel ../sentinel-1.conf
    2. [root@redis-master src]# redis-sentinel ../sentinel-2.conf
    3. [root@redis-master src]# redis-sentinel ../sentinel-3.conf
    1. 4102:X 16 Jul 2021 10:34:17.156 # Sentinel ID is cf64bbac38374fe37a2e744601bea775ed471b86
    2. 4102:X 16 Jul 2021 10:34:17.156 # +monitor master mymaster 127.0.0.1 6379 quorum 2
    3. 4102:X 16 Jul 2021 10:34:17.159 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
    4. 4102:X 16 Jul 2021 10:34:17.161 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
    5. 4102:X 16 Jul 2021 10:34:17.305 * +sentinel sentinel 20bf25e41d173358ad91a183bec4f758be697e5d 127.0.0.1 26381 @ mymaster 127.0.0.1 6379
    6. 4102:X 16 Jul 2021 10:34:28.851 * +sentinel sentinel 6b4d87e41a749e4e1d493d86ad2372f8c52cb0ae 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
    这里我们看到,已经成功监控了一个主节点和两个从节点,并且关联到了已经启动的哨兵。

    模拟主节点宕机

    1. [root@redis-master src]# ps -ef|grep redis
    2. root 3431 3333 0 715 pts/1 00:00:00 redis-cli -p 6380 -a anin
    3. root 3554 3536 0 715 pts/2 00:00:00 redis-cli -p 6381 -a anin
    4. root 4044 1 0 10:21 ? 00:00:00 redis-server 0.0.0.0:6380
    5. root 4051 1 0 10:21 ? 00:00:00 redis-server 0.0.0.0:6381
    6. root 4084 1 0 10:32 ? 00:00:00 redis-server 0.0.0.0:6379
    7. root 4097 4005 0 10:34 pts/5 00:00:00 redis-sentinel *:26381 [sentinel]
    8. root 4102 3979 0 10:34 pts/4 00:00:00 redis-sentinel *:26380 [sentinel]
    9. root 4107 3940 0 10:34 pts/3 00:00:00 redis-sentinel *:26379 [sentinel]
    10. root 4113 1839 0 10:35 pts/0 00:00:00 grep --color=auto redis
    11. [root@redis-master src]# kill -9 4084

    查看哨兵日志

    可以看到,哨兵检测到了6379的redis主节点down掉之后,选举6381的从节点升级为主节点,并且将6380从节点的主节点改为新的主节点。
    1. 4222:X 16 Jul 2021 11:02:57.321 # +sdown master mymaster 127.0.0.1 6379
    2. 4222:X 16 Jul 2021 11:02:57.321 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6379
    3. 4222:X 16 Jul 2021 11:02:57.387 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2
    4. 4222:X 16 Jul 2021 11:02:57.387 # +new-epoch 2
    5. 4222:X 16 Jul 2021 11:02:57.387 # +try-failover master mymaster 127.0.0.1 6379
    6. 4222:X 16 Jul 2021 11:02:57.391 # +vote-for-leader cf64bbac38374fe37a2e744601bea775ed471b86 2
    7. 4222:X 16 Jul 2021 11:02:57.397 # 6b4d87e41a749e4e1d493d86ad2372f8c52cb0ae voted for cf64bbac38374fe37a2e744601bea775ed471b86 2
    8. 4222:X 16 Jul 2021 11:02:57.398 # 20bf25e41d173358ad91a183bec4f758be697e5d voted for cf64bbac38374fe37a2e744601bea775ed471b86 2
    9. 4222:X 16 Jul 2021 11:02:57.458 # +elected-leader master mymaster 127.0.0.1 6379
    10. 4222:X 16 Jul 2021 11:02:57.458 # +failover-state-select-slave master mymaster 127.0.0.1 6379
    11. 4222:X 16 Jul 2021 11:02:57.521 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
    12. 4222:X 16 Jul 2021 11:02:57.521 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
    13. 4222:X 16 Jul 2021 11:02:57.598 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
    14. 4222:X 16 Jul 2021 11:02:57.605 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
    15. 4222:X 16 Jul 2021 11:02:57.605 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
    16. 4222:X 16 Jul 2021 11:02:57.670 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
    17. 4222:X 16 Jul 2021 11:02:58.099 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
    18. 4222:X 16 Jul 2021 11:02:58.099 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
    19. 4222:X 16 Jul 2021 11:02:58.151 # +failover-end master mymaster 127.0.0.1 6379
    20. 4222:X 16 Jul 2021 11:02:58.151 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
    21. 4222:X 16 Jul 2021 11:02:58.152 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
    22. 4222:X 16 Jul 2021 11:02:58.152 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381

原本的没有权限写,也得到了相应的权限

  1. 127.0.0.1:6381> set testkey testkey
  2. OK

down掉的主节点重新上线之后会被切换为主节点吗?

答案是否定的,就比如你被一个小弟抢了你老大的位置,他肯给回你这个位置吗。因此当master 回来之后,他也只能当个小弟。