Sentinel 简介
如上图所示,Redis 高可用是通过Sentinel
来实现的,是Redis
官方推荐的高可用性(HA)解决方案,Sentinel
英文含义是哨兵,放哨的
,可以理解为它是Redis
集群的监控者,监控着所有的master
和slave
机器的健康状况。首先我们来看下它提供了哪些功能。
1.监控(Monitoring):
监控所有主从机的健康状态,当主从机连接出现问题时,会自动变更有问题机器的状态。
2.通知(Notification):
一旦集群的节点有问题,Sentinel
可以通过API
来通知系统管理员或者其他的应用程序。
3.自动执行故障转移(Automatic failover):
如果某个主节点挂掉,Sentinel
会自动踢掉这个主节点,并且从它的从节点中选举一个出来做主节点,其他的从节点也会把这个从节点作为主节点。而且Sentinel
还会持续监控挂掉的主节点,一旦发现活过来了,再次把它加入集群中的一个从节点。
4.作为一个配置提供者(Configuration provider):Sentinel
充当客户端服务发现的权威来源:客户端连接到Sentinels
以请求负责给定服务的当前Redis
主服务器的地址。 如果发生故障转移,Sentinels
将报告新地址。
Sentinel是如何实现的?
Sentinel
并不是一个新东西,它本质上只是一个运行在特殊模式下的Redis
服务器,怎么个特殊法?比如它不支持很多的键值命令,因为它不是用来做存储的,它是用来管理集群的啊。Sentinel
最核心的工作时记录集群节点的信息,比如每个节点的健康状态,以及某个节点故障后,剔除掉坏的机器。
Sentinel 支持哪些集群模式
Sentinel可以监视任意多个主服务器以及这些主服务下的从服务器,因此在集群中你可以一主多从,多主多从。
像这样:
Sentinel
也支持多个Sentinel
集群,几个Sentinel
共同监控一个集群,像这样:
此时,多个Sentinel
会进行相互通信来进行管理集群,比如要对故障节点进行下线,那必须经过多个(可配置)Sentinel
同意才能执行下线,或者选举新的主服务器时,多个Sentinel
也要相互协商。
多个Sentinel
是官方推荐的,因为单个Sentinel
也会有单点故障的问题,万一这个Sentinel
挂掉了咋办?
上手Sentinel
安装
Sentinel
是随redis
安装的,无需再进行额外安装。如果你已经安装了Redis
,可以看下Sentinel
的版本1
redis-sentinel -v
配置
Sentinel
包含了一个名为sentinel.conf
的配置文件,运行一个 Sentinel 所需的最少配置如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13//监视哪个主服务器,2代表执行故障时执行故障转移至少要两个` sentinel'`同意。
sentinel monitor mymaster 127.0.0.1 6379 2
//指定了 Sentinel 主观认为服务器已经断线所需的毫秒数。
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
//
sentinel parallel-syncs mymaster 1
//..继续增加,监视多个服务器
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
failover-timeout
: sentinel集群都遵守一个规则:如果sentinel A推荐sentinel B去执行failover,B会等待一段时间后,自行再次去对同一个master执行failover,这个等待的时间是通过failover-timeout配置项去配置的。从这个规则可以看出,sentinel集群中的sentinel不会再同一时刻并发去failover同一个master,第一个进行failover的sentinel如果失败了,另外一个将会在一定时间内进行重新进行failover,以此类推。parallel-syncs
:在发生failover主备切换时,这个选项指定了最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态。
启动
启动命令如下,配置文件参数是强制性的,必须要,因为sentinel
会使用配置文件保存当前状态,在运行中,配置文件会根据系统状态动态更改,启动时也会重新加载。1
redis-sentinel /usr/local/etc/redis/sentinel.conf
另外,sentinel
默认使用的端口是26379
,可以使用redis
客户端进行连接,如果是本地安装的话,命令如下:1
redis-cli -h 127.0.0.1 -p 26379
Sentinel API
使用 Docker-compose 搭建 Sentinel 集群
借助 Docker-compose ,我们 可以轻松的搭建一个集群环境,docker-compose.yml
配置如下: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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65version: '3'
services:
redis-master1:
image: redis
container_name: redis-master1
volumes:
- "/Users/jarviszhao/docker/redis/conf/:/usr/local/etc/redis/"
ports:
- "6382:6379"
command: redis-server /usr/local/etc/redis/redis-master1.conf
redis-slave1:
image: redis
container_name: redis-slave1
volumes:
- "/Users/jarviszhao/docker/redis/conf:/usr/local/etc/redis/"
ports:
- "6380:6379"
command: redis-server /usr/local/etc/redis/redis-slave1.conf --slaveof redis-master1 6379
links:
- redis-master1
redis-slave2:
image: redis
container_name: redis-slave2
volumes:
- "/Users/jarviszhao/docker/redis/conf:/usr/local/etc/redis/"
ports:
- "6381:6379"
command: redis-server /usr/local/etc/redis/redis-slave2.conf --slaveof redis-master1 6379
links:
- redis-master1
redis-sentinel1:
image: redis
container_name: redis-sentinel1
volumes:
- "/Users/jarviszhao/docker/redis/conf:/usr/local/etc/redis/"
ports:
- "26383:26379"
command: redis-sentinel /usr/local/etc/redis/sentinel1.conf
links:
- redis-master1
redis-sentinel2:
image: redis
container_name: redis-sentinel2
volumes:
- "/Users/jarviszhao/docker/redis/conf:/usr/local/etc/redis/"
ports:
- "26384:26379"
command: redis-sentinel /usr/local/etc/redis/sentinel2.conf
links:
- redis-master1
redis-sentinel3:
image: redis
container_name: redis-sentinel3
volumes:
- "/Users/jarviszhao/docker/redis/conf:/usr/local/etc/redis/"
ports:
- "26385:26379"
command: redis-sentinel /usr/local/etc/redis/sentinel3.conf
links:
- redis-master1
集群中包含三个Sentinel
,一个master
和两个salve
。可以使用docker pause
命令来中断master
的进程,观察是否执行了故障转移。代码见Github 仓库。
Sentinel 详细内部机制
主观下线和客观下线
主观下线
sentinel会向master发送心跳PING来确认master是否存活,如果master在“一定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了(subjectively down, 也简称为SDOWN)。而配置项down-after-milliseconds
就是用来指定这个“一定时间范围”的,单位是毫秒。
客观下线sentinel
会向集群中的其他sentinel
询问故障的master
的状态,当也认为master
已经下线的sentinel
超过配置数量时,sentinel
会认为该master
当前状态是客观下线(ODOWN)。ODOWN需要一定数量的sentinel达成一致意见才能认为一个master客观上已经宕掉,各个sentinel之间通过命令SENTINEL is_master_down_by_addr来获得其它sentinel对master的检测结果。
如果之后master可用了,这个状态就会相应地被清理掉。
ODOWN状态只适用于master,对于不是master的redis节点sentinel之间不需要任何协商,slaves和sentinel不会有ODOWN状态。
Sentinel 与 master ,salve 之间是如何通信的?
Sentinel
与master
,salve
之间有两个异步网络连接。
- 一是命令连接,专门向服务器发送命令,并接受命令回复。
- 二是订阅连接,专门订阅主服务的
__sentinel_hello__
频道。
Sentinel
会以每10秒一次的频率向主从服务器发送info
命令,来获取主从服务器的信息,以及新加入集群其他的sentinel
。Sentinel内部保存着其他Sentinel的信息,如果其他Sentinel有更新,此时保存的信息也会更新。
如何执行失效转移?
当一个主服务被判断为客观下线时,监视这个下线服务器的各个Sentinel会进行协商,选举出个领头Sentinel来执行失效转移。使用 Raft 算法来选出领头Sentinel。确保在一个给定的纪元(epoch)里, 只有一个领头产生。
关于raft 算法
(也是zookeeper
的核心算法)
http://www.jdon.com/artichect/raft.html
参考
01.Redis Sentinel 官方文档
02.Redis主从集群的Sentinel配置
03.使用Docker Compose部署基于Sentinel的高可用Redis集群
04.Redis 高可用(1)——Sentinel 篇
Redis Sentinel机制与用法(一)