Sentinel 实现高可用

Sentinel 是 Redis 的高可用性解决方案:有一个或多个 Sentinel 实例组成的 Sentinel 系统可以检测多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自己将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

特点:动态感知上下线,动态切换主服务器。

Sentinel 本质上只是一个运行在特殊模式下的 Redis 服务器,执行的工作和普通 Redis 服务器不同。

Sentinel 实现高可用的流程

  1. sentinel 集群通过配置文件发现 matser,启动时会监控 master。
  2. 向 master 发送 info 命令,获取所有 slave 节点。
  3. sentinel 集群向 Redis 主从服务器发送 hello 信息(心跳),包括 sentinel 本身的 IP、端口、id 等内容,以此来向其他 sentinel 宣告自己的存在。
  4. sentinel 集群通过订阅接受其他 sentinel 发送的 hello 信息,以此来发现监控同一个主服务器的其他 sentinel。集群之间会互相创建命令连接用于通信,因为已经有主从服务器作为发送和接受 hello 信息的中介,sentinel 之间不会创建订阅连接。
  5. sentinel 集群使用 ping 命令来检测实例的状态,如果在指定的时间内没有回复或者返回错误的信息,那么该实例被判为下线。
  6. 当 failover 主备切换被触发后 ,并不会马上执行,还需要 sentinel 中的大多数 sentinel 授权后才可以进行 failover,即进行 failover 的 sentinel 会去获得指定 quorum 个 sentinel 的授权,成功后进入 odown 状。如在 5 个 sentinel 中配置了 2 个 quorum,等到 2 个 seninel 认为 master 死了就执行 failover。
  7. 当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个 sentine 会进行协商,选举出一个领导 sentinel,并由领头 sentinel 对下线主服务器进行故障转移操作。
  8. sentinel 向选为 master 的 slaver 发送 slaverof no one 命令 。选择 slaver 的条件时 sentinell 首先会根据 slaver 的优先级来进行排序,优先级越大排名越靠前。优先级相同,则查看复制偏移量,复制偏移量越大越靠前。如果优先级相同,就选择进程 id 较少的。
  9. sentinel 被授权后,它就会获得宕机的 matser 的一份最新配置版本号,当 failover 执行结束之后,这个版本号将会被用于最新的配置,通过广播形式通知其他 sentinel,其他 sentinel 则更新对应 master 的配置。

Redis Sentinel 中的 3 个定时任务

  1. 每 10 秒每个 Sentinel 节点对 master 节点和 slave 节点执行 info 操作:

    • 首先向 master 节点发送 info 信息,或者以下信息:
      • 获取主服务器本身的信息,包括 run_id 域记录的服务器运行 ID,以及 role 域记录放入服务器角色
      • 关于主服务器属下所有从服务器的信息(不需要配置从服务器信息 ,自动获取)。
    • 后续一起向从服务器发送 info 信息
      • 从服务器运行 id、角色 role
      • 主服务器的 IP 地址和端口
      • 主从服务器的连接状态,从服务器的优先级 slave_priority 和复制偏移量 slave_repl_offset

    image-20200903171844563

  2. 每 2 秒每个 sentinel 节点通过命令向所有被监视的主服务器和从服务器发送命令,channel(sentinel:hello)

    • 以 s_开头的关于 sentinel 信息,包括 ip 地址、端口号、运行 id、epoch
    • 以 m_开头的主服务器信息,包括名字、ip 地址、端口号、epoch

    image-20200903172818711

  3. 每一秒每个 sentinel 节点对 master 节点和 slave 节点以及其余的 sentinel 执行 ping 操作

    image-20200903172942096

    主观下线和客观下线

    主观下线:当前 sentinel 节点认为某个 redis 节点不可用

    客观下线:所有 sentinel 节点认为某个 redis 节点不可用-一定数量的 sentinel 认为节点不可用,然后同步给其他 sentinel 节点

    故障转移

    1. 领导者选举

      作用:选举出一个 sentinel 节点作为领导者去进行故障转移工作

      规则:

      • 所有在线的 sentinel 都可以被选为领头 sentinel
      • 每次进行领头 sentinel 选举之后,不论选举是否成功,所有 sentinel 的 epoch 都会自增+1
      • 每一个 epoch 中,所有 sentinel 都可以将某个 sentinel 作为局部领导 sentinel

      过程:

      • 每个做主观下线的 sentinel 节点向其他 sentinel 节点发送选票,选举自己为领导者
      • 收到命令的 sentinel 节点如果还没有同意过其他 sentinel 发送的选票,那么就会同意,否则拒绝。
      • 如果该 sentinel 节点发现自己的票数已经达到 quorum 的值,就会成为领导者
      • 如果这个过程出现多个 sentinel 成为领导者,则会等待一段时间重新选举
    2. 选出新的 master 节点

      规则:

      • 选择 slave-priority 最高的 slave 节点
      • 选择偏移量最大的节点
      • 选择 runId 最小的-启动最早的
    3. 更改 slave 节点的 master 节点

      当选举出新的 master 节点后,会将其余的节点变更为新的 master 节点的 slave 节点,如果原有的 master 节点重新上线,成为新的 master 节点的 slave 节点

    4. 通知客户端

      当所有节点配置结束后,sentinel 会通知客户端节点变更信息

    5. 客户端连接新的 master 节点

      客户端收到节点信息后,会连接新的 master 节点

    避免写命令丢失

    因为 redis 是异步复制,没有办法避免数据的丢失。可以在 redis.conf 通过以下配置来使得数据不会丢失

    1
    2
    3
    4
    # master 最少得有多少个健康的slave存活才能执行写命令
    min-slaves-to-write 1
    # 延迟少于min-slaves-max-lag 秒的slave才认为是健康的slave
    min-slaves-max-lag 10