一.介绍
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
它的主要功能有以下几点:
• 不时地监控redis是否按照预期良好地运行;
• 如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端);
• 能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址。
Sentinel支持集群
很显然,只使用单个sentinel进程来监控redis集群是不可靠的,当sentinel进程宕掉后(sentinel本身也有单点问题,single-point-of-failure)整个集群系统将无法按照预期的方式运行。所以有必要将sentinel集群,这样有几个好处:
• 即使有一些sentinel进程宕掉了,依然可以进行redis集群的主备切换;
• 如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);
• 如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息。
Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用:
• 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
• 扩展主节点的读能力,分担主节点读压力。
但是问题来了:
• 一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。
• 主节点的写能力受到单机的限制。
• 主节点的存储能力受到单机的限制。
第一个问题,我们接下来讲的Sentinel就可以解决。而后两个问题,Redis也给出了方案Redis Cluster。
二. Redis主从部署
1. 部署redis主备节点
6379端口部署为主节点:
port 6379
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"
dir "/var/redis/data/"
6380端口部署为备节点:
port 6380
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
dir "/var/redis/data/"
slaveof 127.0.0.1 6379
这里只启动一个备节点,当然也可以启动多个备节点。
2. 确认Redis主从关系
6379端口主节点视角:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=112,lag=1
6380端口备节点视角:
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
3. 在6379主节点写入数据,数据会同时备份到从节点6380。
三. Redis Sentinel部署
这里部署两个Sentinel节点,部署方法是相同的(端口不同)。有两个端口:26379和26380,下面的配置以26379为例。
// Sentinel节点的端口
port 26379
dir /var/redis/data/
logfile "26379.log"
// 当前Sentinel节点监控 127.0.0.1:6379 这个主节点
// 2代表判断主节点失败至少需要2个Sentinel节点节点同意
// mymaster是主节点的别名
sentinel monitor mymaster 127.0.0.1 6379 2
//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000
//当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel parallel-syncs mymaster 1
//故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000
启动(两种方法)
redis-sentinel sentinel_26379.conf
redis-server sentinel_26379.conf --sentinel
redis-cli连接sentinel服务,确认关系:
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=1,sentinels=2
拓扑结构如下图所示:
四.故障实验
1. 我们先关掉端口6379的主节点
此时,Redis Sentinel对主节点进行客观下线(Objectively Down, 简称 ODOWN)的判断,确认主节点不可达,则通知从节点中止复制主节点的操作。当主节点下线时长超过配置的下线时长30000毫秒,Redis Sentinel执行故障转移操作。
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=odown,address=127.0.0.1:6379,slaves=1,sentinels=2
发现状态变为odown,而另一台sentinel也显示6379端口处于sdown状态。
查看主节点信息,发现主节点已变成6380。
127.0.0.1:26379> sentinel masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6380"
而原来的主节点6379已变为从节点。
127.0.0.1:26379> sentinel slaves mymaster
1) 1) "name"
2) "127.0.0.1:6379"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6380"
7) "runid"
8) ""
9) "flags"
10) "s_down,slave,disconnected" //状态变为s_down,断开连接
6380节点也显示主节点状态为down了。
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
2. 我们重新启动6379端口
6379端口变为了slave,6380变成了master:
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
redis-sentinel信息:
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:6380,slaves=1,sentinels=2
说明sentinel选取了新的节点作为master节点。
从上面的逻辑架构和故障转移试验中,可以看出Redis Sentinel的以下几个功能。
• 监控:Sentinel节点会定期检测Redis数据节点和其余Sentinel节点是否可达。
• 通知:Sentinel节点会将故障转移通知给应用方。
• 主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。
• 配置提供者:在Redis Sentinel结构中,客户端在初始化的时候连接的是Sentinel节点集合,从中获取主节点信息。