Redis高可用性—Sentinel配置

简介

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

Redis Sentinel 是一个分布式系统,可以在一个架构中运行多个 Sentinel 进程,这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器,在启动一个普通 Redis 服务器时通过给定 --sentinel选项来启动 Redis Sentinel 。

获取Sentinel

Sentinel已经包含在redis的源码包中,可以直接获取
在这里插入图片描述

配置Sentinel

1、将sentinel配置文件复制到/etc/redis/,先修改配置文件,再将配置文件发送各个至slave

[root@server5 ~]#  vim /etc/redis/sentinel.conf
protected-mode no #禁止安全检测
sentinel monitor mymaster 172.25.14.7 6379 2 #表示要有两个sentinel通过,确认后master才可以客观下线,在只有少数sentinel进程正常工作情况下,sentinel时不能执行自动故障切换的
sentinel down-after-milliseconds mymaster 10000 
sentinel failover-timeout mymaster 30000
sentinel parallel-syncs mymaster 1
daemonize no ###后台运行

2、启动服务,三个节点都做,为了方便查看,将进程不打入后台

# redis-server /etc/redis/sentinel.conf

可以看到,此时sentinel有三个,master为172.25.254.5,两个slave
在这里插入图片描述
登陆master客户端,查看详细信息

# redis-cli
127.0.0.1> INFO

在这里插入图片描述
3、将master执行SHUTDOWN
在这里插入图片描述
此时通过sentinel,自动将master迁移值172.25.254.7
在这里插入图片描述
在这里插入图片描述
登陆master将查看信息,此时只有一个slave存活,故障的master此时可以切换为新的slave与新master去通信
在这里插入图片描述

在redis配置文件中添加master的IP
在这里插入图片描述
再次查看master信息,slave已经有两个

在这里插入图片描述
在这里插入图片描述
同时可以查询数据,因为slave提升为新master后,数据还未做变更,slave每次同步时候只允许去同步一个master,当新master上线后,会清空旧master的数据,slave会同步新master的数据,若master端为空,则会与新master数据保持一致,因此可以开启持久化保存数据。

各选项功能
  • down-after-milliseconds指定了sentinel认为服务器已经断线的毫秒数。
    如果在给定毫秒内服务器没有返回sentinel发送的PING命令的回复,或者返回一个错误,那么sentinel将这个服务器标记为主观下线(subjectively down,SDOWN)
    只有一个sentinel将服务器标记为主观下线并不一定会引起服务器的自动故障迁移,只有在数量足够的sentinel都将该孤鹜齐标记为主观下线后,服务器才会被标记为客观下线,才会发起自动故障迁移。
  • parallel-syncs指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间越长。但是如果从属服务器配置为提供旧数据,则可能不希望所有从属服务器同时与主服务器重新同步。 虽然复制过程对于从属设备大部分是非阻塞的,但是有一段时间它停止从主设备加载批量数据。 您可能希望通过将此选项设置为值1来确保一次只能访问一个从服务器处于不能处理命令请求的状态

主观下线和客观下线

  • 主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
  • 客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)

如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线。
服务器对 PING 命令的有效回复可以是以下三种回复的其中一种:
返回 +PONG 。
返回 -LOADING 错误。
返回 -MASTERDOWN 错误。
如果服务器返回除以上三种回复之外的其他回复, 又或者在指定时间内没有回复 PING 命令, 那么 Sentinel 认为服务器返回的回复无效(non-valid)。
注意, 一个服务器必须在 master-down-after-milliseconds 毫秒内, 一直返回无效回复才会被 Sentinel 标记为主观下线。

举个例子, 如果 master-down-after-milliseconds 选项的值为 30000 毫秒(30 秒), 那么只要服务器能在每 29 秒之内返回至少一次有效回复, 这个服务器就仍然会被认为是处于正常状态的。

从主观下线状态切换到客观下线状态并没有使用严格的法定人数算法(strong quorum algorithm), 而是使用了流言协议: 如果 Sentinel 在给定的时间范围内, 从其他 Sentinel 那里接收到了足够数量的主服务器下线报告, 那么 Sentinel 就会将主服务器的状态从主观下线改变为客观下线。 如果之后其他 Sentinel 不再报告主服务器已下线, 那么客观下线状态就会被移除。

客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。

只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。

Sentinel API

在默认情况下, Sentinel 使用 TCP 端口 26379 (普通 Redis 服务器使用的是 6379 )。
Sentinel 接受 Redis 协议格式的命令请求, 所以你可以使用 redis-cli 或者任何其他 Redis 客户端来与 Sentinel 进行通讯。

有两种方式可以和 Sentinel 进行通讯:

第一种方法是通过直接发送命令来查询被监视 Redis 服务器的当前状态, 以及 Sentinel 所知道的关于其他 Sentinel 的信息, 诸如此类。
另一种方法是使用发布与订阅功能, 通过接收 Sentinel 发送的通知: 当执行故障转移操作, 或者某个被监视的服务器被判断为主观下线或者客观下线时, Sentinel 就会发送相应的信息。

以下列出的是客户端可以通过订阅来获得的频道和信息的格式: 第一个英文单词是频道/事件的名字, 其余的是数据的格式。
当格式中包含 instance details 字样时, 表示频道所返回的信息中包含了以下用于识别目标实例的内容:
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>

@ 字符之后的内容用于指定主服务器, 这些内容是可选的, 它们仅在 @ 字符之前的内容指定的实例不是主服务器时使用。

    +reset-master :主服务器已被重置。
    +slave :一个新的从服务器已经被 Sentinel 识别并关联。
    +failover-state-reconf-slaves :故障转移状态切换到了 reconf-slaves 状态。
    +failover-detected :另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。
    +slave-reconf-sent :领头(leader)的 Sentinel 向实例发送了 [SLAVEOF](/commands/slaveof.html) 命令,为实例设置新的主服务器。
    +slave-reconf-inprog :实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。
    +slave-reconf-done :从服务器已经成功完成对新主服务器的同步。
    -dup-sentinel :对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。
    +sentinel :一个监视给定主服务器的新 Sentinel 已经被识别并添加。
    +sdown :给定的实例现在处于主观下线状态。
    -sdown :给定的实例已经不再处于主观下线状态。
    +odown :给定的实例现在处于客观下线状态。
    -odown :给定的实例已经不再处于客观下线状态。
    +new-epoch :当前的纪元(epoch)已经被更新。
    +try-failover :一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中(waiting to be elected by the majority)。
    +elected-leader :赢得指定纪元的选举,可以进行故障迁移操作了。
    +failover-state-select-slave :故障转移操作现在处于 select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。
    no-good-slave :Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。
    selected-slave :Sentinel 顺利找到适合进行升级的从服务器。
    failover-state-send-slaveof-noone :Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。
    failover-end-for-timeout :故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the new master anyway)。
    failover-end :故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。
    +switch-master :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。
    +tilt :进入 tilt 模式。
    -tilt :退出 tilt 模式。

故障转移

一次故障转移操作由以下步骤组成:

  • 发现主服务器已经进入客观下线状态。
  • 对我们的当前纪元进行自增(详情请参考 Raft leader election ), 并尝试在这个纪元中当选。
  • 如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选。 如果当选成功, 那么执行以下步骤。
  • 选出一个从服务器,并将它升级为主服务器。
  • 向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。
  • 通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。
  • 向已下线主服务器的从服务器发送 SLAVEOF 命令, 让它们去复制新的主服务器。
  • 当所有从服务器都已经开始复制新的主服务器时, 领头 Sentinel 终止这次故障迁移操作。

每当一个 Redis 实例被重新配置(reconfigured) —— 无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 —— Sentinel 都会向被重新配置的实例发送一个 CONFIG REWRITE 命令, 从而确保这些配置会持久化在硬盘里。
Sentinel 使用以下规则来选择新的主服务器:

  • 在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被淘汰。
  • 在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被淘汰。
  • 在经历了以上两轮淘汰之后剩下来的从服务器中, 我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器; 如果复制偏移量不可用, 或者从服务器的复制偏移量相同, 那么带有最小运行 ID 的那个从服务器成为新的主服务器。
Sentinel的三个节点部署存在的复制问题

Redis的配置一主两从,三个sentinel部署如下:
在这里插入图片描述
当M1发生故障时候,通过sentinel可以挑选出新的M2来保障服务的高可用性,R3会去连接新的master去同步数据。旧M1也可以成为新M2的slave。
如果网络分区隔离了旧的主M1,因此从属R2被提升为主。 但是,与旧主服务器位于同一分区的客户端(如C1)可能会继续将数据写入旧主服务器。 那么如果网络恢复,旧M1变成新的slave时,它会去同步M2上的数据,并且会丢弃自己的数据,这个数据将永远丢失。
在这里插入图片描述

上面这种情况是不太好的,使用以下Redis复制功能可以缓解此问题,如果主服务器检测到不再能够将其写入传输到指定数量的从服务器,则允许停止接受写入。
在redis.conf配置文件中

min-slaves-to-write 1
min-slaves-max-lag 10

Redis实例作为主服务器时,如果无法写入至少1个从服务器,将停止接受写入。 由于复制是异步的,因此无法实际写入意味着从属设备已断开连接,或者未向我们发送异步确认超过指定的最大延迟秒数。
使用此配置,上例中的旧Redis主M1将在10秒后变为不可用。 当分区恢复时,Sentinel配置将收敛到新的配置,客户端C1将能够获取有效配置并继续使用新主设备。


版权声明:本文为weixin_43314056原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。