Redis 4.x系列(十七):Redis Sentinel(高可用-主从切换哨兵模式)
简单的复制机制并不能保证高可用,若仅仅只配置了master-slave复制,当 master无法提高服务时,整个 Redis 服务就停了,slave 无法接替 master 继续提供服务。
Redis 为实现高可用提供了基于复制机制 的 **Sentinel(哨兵)**模式解决方案。Redis Sentinel Documentation,Redis 的 Sentinel 文档
Sentinel 介绍
Redis Sentinel(哨兵) 是 Redis 原生支持的高可用性方案。 Sentinel 可以管理多个 Redis 服务器(实例),充当了 Redis主/从实例的守卫者。。
Sentinel 主要功能
- 监测: Sentinel 会持续检测主-从实例运行是否正常。
- 通知: 当 Redis 服务器出现故障,Sentinel 可以通过 API 通知管理员或其它应用程序。
- 自动故障迁移:当主服务器出现故障,Sentinel 会自动执行故障迁移操作,将故障服务器的从实例提升为主实例, 故障服务器其它从实例从新的主服务器上复制。
- 配置提供者:客户端通过 Sentinel 访问 Redis 主服务器,如果发生故障迁移,Sentinel 将返回新的主服务器地址。
Sentinel 分布式优势
Redis Sentinel 支持分布式部署,在一个架构中可运行多个 Sentinel 进程,多个 Sentinel 进程协同工作。
- 只有当多个 Sentinel 都同意master不可用时,才会执行故障检测和迁移,降低了误报的可能性。
- 即使某几个 Sentinel 停止工作,整体架构的 Sentinel 也能正常工作,保证了高可用性,使系统抵御了故障。
多个 Sentinel 进程使用流言协议(gossip protocols)来接收主实例失效的信息,并基于投票协议(仲裁系统)来决定是否对主实例进行故障迁移。
Redis 安装包包含了可执行文件redis-sentinel
,使用ls -l
命令可以看到redis-sentinel实际上是redis-server的链接文件,实际上它只是一个运行在特殊模式下的 Redis 服务。
Sentinel 基本知识
- 需要至少三个 Sentinel 实例才能实现强大的高可用部署。这是由对主实例是否进行故障迁移的投票机制决定的。
- 为确保高可用,三个实例应独立部署在不同物理服务器或虚拟机上。
- Sentinel + Redis 分布式系统无法确保在发生故障时的数据被持久化(保存),因为 Redis 主-从复制是异步执行的。可以通过持久化方式的详细设置来尽可能降低数据丢失的可能和减少丢失的数据。
- 客户端也需要支持 Sentinel,主流的客户端基本有支持 Sentinel,但不是全部。
- 可以的话,在开发环境多测试,否则无法确保生产环境中的高可用设置的安全。
- Sentinel使用Docker部署或其他形式的网络地址转换(NAT)或端口映射时应谨慎使用。端口映射或NAT方式可能会阻止其他 Sentinel 进程的自动发现以及主服务器的从属列表。
Sentinel 部署
Sentinel 启动
Sentinel 启动有两种方式:
执行redis-sentinel可执行文件
./redis-sentinel sentinel.conf
以sentinel模式启动redis-server
redis-server sentinel.conf –sentinel
运行 sentinel 必须指定配置文件,当从实例和其他哨兵的信息发生改变时,sentinel 的配置文件也将被更新,系统需要使用此文件来保存当前状态,下次重启时加载进行状态还原。如果没有指定配置文件,或没有写的权限,sentinel将拒绝启动。
Sentinel 默认侦听与 TCP 26379
端口的连接,注意防火墙开放此端口。
Sentinel 会向主实例发送 INFO REPLICATION命令来获取从实例的信息,即使实例有多级,也可以通过递归找到他们。实际上,每个 Sentinel 进程每 10 秒钟会向其监控的所有 Redis 实例(包括主实例和被检测到的从实例)发送INFO REPLICATION命令,来获取整个主从复制拓扑结构的最新信息。
为了探测其他哨兵及与其他哨兵通信,每个Sentinel进程每两秒会向一个名为_sentinel_:hello
的频道发布一条消息,报告其自身及所监控主实例的状态。可以订阅该频道就能发现其他哨兵的信息。
Sentinel 配置
Redis 源码包已包含一个名为 sentinel.conf 的配置文件,典型的最小配:
- 典型最小配置:
1
2
3
4
5
6
7
8
9
10
11//第一组:指定监听的主服务器并命名,判致断主服务器失效至少需要 2 个 sentinel 一同意,否则不会触发故障迁移
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
//第二组:sentinel 可同时监控多组master
sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5 - sentinel 监控主实例的: 只需要指定要监视的主服务器并命名,无需指定从服务器,Sentinel 会使用从服务器的附加信息自动更新配置(便于在重启时持有信息),从服务器升级为主服务器时,或者发现新的Sentinel,也会重写配置。 quorum:这里理解为参与仲裁,对于标记主服务器故障达成一致的 Sentinel 的数量。
1
sentinel monitor <master-group-name> <ip> <port> <quorum>
仲裁仅用于检测故障。在有多个 Sentinel 进程的投票中,真正执行故障转移的是其中一个需要被选为故障迁移的领导者并被授权执行的 Sentinel,同时至少有三个 Sentinel 正常有效,否则 Sentinel不会启动故障迁移。 - 其它选项的配置:
1
sentinel <option_name> <master_name> <option_value>
- down-after-milliseconds:实例无法访问的时间(连接超时,单位毫秒),则认为此实例已关闭。Sentinel每秒钟会向实例发送PING命令来检查其是否可达。
- failover-timeout:设置故障迁移超时时间(单位毫秒)。多个 Sentinel 不会同时执行故障迁移同一个主服务器,第一个被授权的Sentinel执行失败,则另一个会被授权执行。
- parallel-syncs:设置最多可以有多少个从实例可以同时从新的主实例进行数据同步。数据越小,完成故障迁移的时间就越长。
- sentinel 监控主服务器连接配置密码认证
如果 master 开启了客户端连接需要密码安全认证(requirepass), sentinel监控主服务器连接必须配置sentinel auth-pass,且sentinel auth-pass配置必须在sentinel monitor - 服务运行时,可使用SENTINEL SET命令修改所有配置参数。
Sentinel 配置示例
在 Linux 上部署 Redis 和 Sentinel,因为 Redis 是单线程,为了充分利用计算机资源,可以在一台物理机上部署多个实例。
生产环境上部署Sentinel原则上要独立部署在不同的服务器上,防止因物理服务器崩溃导致所有 Redis 服务无法提供服务。
下面是在单台计算机上模拟部署,Redis 主从配置见Redis 4.x系列(十五):Redis 主从复制、调优和故障分析。
- Redis 服务部署一主两从:
Master:127.0.0.1 6379
Slave-1:127.0.0.1 6380
Slave-2:127.0.0.1 6381 - Sentinel 至少部署三个:
Sentinel-1:127.0.0.1 26379
Sentinel-2:127.0.0.1 26380
Sentinel-3:127.0.0.1 26381 - 主要配置如下,其它两个Sentinel同步修改端口。 Redis 主服务器(master)开启了连接密码认证,密码是:123456。
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1 - Sentinel 启动成功后,可以看到如下输出日志信息
+monitor master mymaster 127.0.0.1 6379 quorum 2
- 查看sentinel.conf配置,在文件末尾有写入主从服务器的信息,如下:
#Generated by CONFIG REWRITE(重写配置)
sentinel known-slave mymaster 127.0.0.1 6380
sentinel known-slave mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26381 a15491db624203b5a729352a6cfd6cf01c6b3448
sentinel known-sentinel mymaster 127.0.0.1 26380 653f80ac9e0a6d8c7b2fd3989d37f2764a4f999b
sentinel current-epoch 0 - 连接 Sentinel,查看 Sentinel部署信息
redis-cli -p 26379
127.0.0.1:26379> info sentinel
#Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3 - 查看服务器信息
redis-cli -p 26379
#查看连接的主实例信息
127.0.0.1:26379> sentinel master mymaster#查看连接的从实例信息
SENTINEL slaves mymaster#查看连接的sentinels信息
SENTINEL sentinels mymaster - 获取当前 master 的地址
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
- “127.0.0.1”2) “6380”
Sentinel 主从切换
测试 Sentinel 主从切换实现故障迁移。
- 让主服务器休眠 30 秒,模拟主服务器连接超时
redis-cli -p 6381 DEBUG sleep 30
- 输出日志,从日志中可以了解投票、从服务器提升为主服务器的过程。下面日志是 6381 为主服务器时休眠。
每个 Sentinel 都会检测到主服务器国**+sdown**(subjectively down,主观下线)事件而关闭,然后**+sdown事件升级为+odown**(objectively down,客观下线),表示多个 Sentinel 一致同意主服务器无法访问。
Sentinel 开启投票选取新领导者(新主实例),执行故障迁移。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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
4232428:X 19 Nov 16:05:18.251 # +sdown master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.328 # +sdown master mymaster 127.0.0.1 6381
32429:X 19 Nov 16:05:18.356 # +sdown master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.380 # +odown master mymaster 127.0.0.1 6381 #quorum 2/2
32427:X 19 Nov 16:05:18.380 # +new-epoch 9
32427:X 19 Nov 16:05:18.380 # +try-failover master mymaster 127.0.0.1 6381
32429:X 19 Nov 16:05:18.439 # +odown master mymaster 127.0.0.1 6381 #quorum 3/2
32429:X 19 Nov 16:05:18.440 # +new-epoch 9
32429:X 19 Nov 16:05:18.440 # +try-failover master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.446 # +vote-for-leader 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 9
32429:X 19 Nov 16:05:18.521 # +vote-for-leader a15491db624203b5a729352a6cfd6cf01c6b3448 9
32428:X 19 Nov 16:05:18.522 # +new-epoch 9
32427:X 19 Nov 16:05:18.523 # a15491db624203b5a729352a6cfd6cf01c6b3448 voted for a15491db624203b5a729352a6cfd6cf01c6b3448 9
32429:X 19 Nov 16:05:18.523 # 6a46c8a922ce42b64d6742be5c6703e2f7a3adae voted for 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 9
32428:X 19 Nov 16:05:18.571 # +vote-for-leader 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 9
32429:X 19 Nov 16:05:18.572 # 653f80ac9e0a6d8c7b2fd3989d37f2764a4f999b voted for 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 9
32427:X 19 Nov 16:05:18.572 # 653f80ac9e0a6d8c7b2fd3989d37f2764a4f999b voted for 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 9
32427:X 19 Nov 16:05:18.581 # +elected-leader master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.581 # +failover-state-select-slave master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.647 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.648 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:18.732 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
32428:X 19 Nov 16:05:19.327 # +odown master mymaster 127.0.0.1 6381 #quorum 3/2
32428:X 19 Nov 16:05:19.327 # Next failover delay: I will not start a failover before Mon Nov 19 16:07:18 2018
32427:X 19 Nov 16:05:19.646 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:19.647 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:19.647 # +failover-end master mymaster 127.0.0.1 6381
32427:X 19 Nov 16:05:19.647 # +switch-master mymaster 127.0.0.1 6381 127.0.0.1 6380
32427:X 19 Nov 16:05:19.648 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32429:X 19 Nov 16:05:19.701 # +config-update-from sentinel 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 127.0.0.1 26379 @ mymaster 127.0.0.1 6381
32429:X 19 Nov 16:05:19.701 # +switch-master mymaster 127.0.0.1 6381 127.0.0.1 6380
32429:X 19 Nov 16:05:19.701 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32428:X 19 Nov 16:05:19.702 # +config-update-from sentinel 6a46c8a922ce42b64d6742be5c6703e2f7a3adae 127.0.0.1 26379 @ mymaster 127.0.0.1 6381
32428:X 19 Nov 16:05:19.702 # +switch-master mymaster 127.0.0.1 6381 127.0.0.1 6380
32428:X 19 Nov 16:05:19.703 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32427:X 19 Nov 16:05:24.669 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32429:X 19 Nov 16:05:24.706 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32428:X 19 Nov 16:05:24.764 # +sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
OK
root@test_zhengguangxing:/usr/local/redis/bin-6379# 32428:X 19 Nov 16:05:42.573 # -sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32429:X 19 Nov 16:05:42.580 # -sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
32427:X 19 Nov 16:05:42.609 # -sdown slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380 - 验证已切换主实例
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
- “127.0.0.1”
- “6380”
Sentinel 下线判断
- 主观下线(sdown):指的是单个 Sentinel 实例对服务器做出的下线判断。
- 客观下线(odown):指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)
Sentinel 发现机制
Sentinel 必须与其他 Sentinel 进行通信来自动确认对方的可用性并交换信息。
Sentinel 使用 Redis 的 Pub/Sub(发布订阅) 功能来发现监视相同主服务器和从服务器及其他 Sentinel,新的 Sentinel 会在 10 秒内被添加到整个 Sentinel 集群中。
Sentinel 管理
- 连接 Sentinel
redis-cli -p 26379
- 获取主服务器IP和端口
SENTINEL get-master-addr-by-name mymaster
- 获取主实例信息
sentinel master mymaster
sentinel masters
- 获取所有从实例信息
sentinel slaves mymaster
- 更新 Sentinel 配置
sentinel set mymaster down-after-milliseconds mymaster 2000
- 执行脚本
在 sentinel.conf 可配置通知脚本。例如希望当发生 Sentinel(如:+sdown, +odown) 事件发生时自动发送电子邮件通知管理员。一个事件通知 Python 脚本
Redis 4.x系列(十七):Redis Sentinel(高可用-主从切换哨兵模式)