Redis Sentinel (哨兵模式)
Redis Sentinel 是redis为高可用提供的一种实现方式
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
1、监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
2、提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
3、自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
虽然 Redis Sentinel 为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel 。
Sentinel的分布式性质
Redis Sentinel是一个分布式系统:
Sentinel本身设计为在有多个Sentinel进程协同合作的配置中运行。具有多个Sentinel进程进行协作的优点如下:
1、当多个哨兵就给定的主机不再可用这一事实达成共识时,将执行故障检测。这降低了误报的可能性。
2、即使不是所有的Sentinel进程都在工作,Sentinel仍能正常工作,从而使系统能够应对故障。毕竟,拥有故障转移系统本身就是一个单点故障,这没有任何乐趣。
启动Sentinel的两种方式
对于 redis-sentinel 程序, 你可以用以下命令来启动 Sentinel 系统:
redis-sentinel /path/to/sentinel.conf
对于 redis-server 程序, 你可以用以下命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:
redis-server /path/to/sentinel.conf --sentinel
两种方法的工作原理相同,都是使用sentinel配置文件来启动Sentinel
但是,在运行Sentinel时必须使用配置文件,因为系统将使用此文件来保存当前状态,以便在重启时重新加载。如果未提供配置文件或配置文件路径不可写,Sentinel只会拒绝启动。
Sentinels默认情况下会监听TCP端口26379的连接,因此,为了使Sentinels正常工作,必须打开服务器的端口26379 才能从其他Sentinel实例的IP地址接收连接。否则,Sentinels无法讨论也不能就该做什么达成共识,因此将永远不会执行故障转移。
配置 Sentinel
Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。
运行一个 Sentinel 所需的最少配置如下所示:
#主节点信息,格式:sentinel <master-name> <ip> <redis-port> <quorum>;
#<master-name> 自定义主节点名称;
#<ip> <redis-port> 主节点的ip和端口;
#<quorum> 多少个主节点检测到主节点有问题就进行故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
#sentinel与master的心跳时间(毫秒)
sentinel down-after-milliseconds mymaster 60000
#故障转移超时时间(毫秒),默认180秒
sentinel failover-timeout mymaster 180000
#parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。
sentinel parallel-syncs mymaster 1
第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。
不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移, 并预留一个给定的配置纪元 (configuration Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。
换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。
主观下线和客观下线
前面说过, Redis 的 Sentinel 中关于下线(down)有两个不同的概念:
主观下线(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 标记为主观下线。
每个 Sentinel 都需要定期执行的任务
1、每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令。
2、如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。
3、如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。
4、如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线。
5、在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
6、当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器重新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主观下线状态就会被移除。
实例
前提:在我们运行了一个有主从关系redis实例之后,我这里运行了一个127.0.0.1:6379的实例
1、修改sentinel配置文件
vi sentinel.conf #在redis的跟目录下
port 26379 #端口
daemonize yes #后台启动
protected-mode no #保护模式如果开启只接受回环地址的ipv4和ipv6地址链接,拒绝外部链接,而且正常应该配置多个哨兵,避免一个哨兵出现独裁情况,如果配置多个哨兵那如果开启也会拒绝其他sentinel的连接。导致哨兵配置无法生效。
logfile "/data/redis/logs/sentinel.log" #指明日志文件
dir "/data/redis/sentinel"
sentinel monitor mymaster 127.0.0.1 6379 1 #哨兵监控的master。
sentinel down-after-milliseconds mymaster 30000 #master或者slave多少时间(默认30秒)不能使用标记为down状态。
sentinel failover-timeout mymaster 9000 #若哨兵在配置值内未能完成故障转移操作,则任务本次故障转移失败。
sentinel auth-pass mymaster redispass #如果redis配置了密码,那这里必须配置认证,否则不能自动切换
2、配置完配置文件之后,启动服务
redis--sentinel sentinel.conf #启动服务
看到以下信息,说明启动成功
[root@localhost bin]# redis-sentinel sentinel.conf
54808:X 30 Jun 2020 09:59:47.154 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
54808:X 30 Jun 2020 09:59:47.256 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=54808, just started
54808:X 30 Jun 2020 09:59:47.256 # Configuration loaded
3、然后我们可以登录进redis的哨兵实例中(默认端口26379,如有多个,需自己设置端口号),执行sentinel master mymaster来查看哨兵监听的服务器(mymaster为服务器名称)
[root@localhost bin]# redis-cli -p 26379
127.0.0.1:26379> sentinel master mymaster
1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6379"
7) "runid"
8) "722adf9bdd3a1a1b4a526983b72a7718cd297162"
9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "666"
19) "last-ping-reply"
20) "666"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "7996"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "701190"
29) "config-epoch"
30) "0"
31) "num-slaves"
32) "0"
33) "num-other-sentinels"
34) "0"
35) "quorum"
36) "1"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"