一、哨兵模式
1.1简介
前面所配置的主从模式,虽然实现了读写分离,解决了数据备份问题和单机模式可能存在的性能问题,但是也引入了新的问题:
由于主从模式下可以将读写操作分配给不同的 Redis 节点,从而达到提高系统吞吐量的目的,但也正是因为这种方式造成了使用上的不便。因为客户端连接到不同的 Redis 节点时,都需要指定特定的 IP 端口,若所连接的节点因为故障下线了,主从模式便无法通知客户端切换到另一个可用节点,只能靠手动更改客户端配置并重连。
尤其是如果故障下线的是主节点,那么所有的从节点便会因为没有主节点而同步中断,整个集群会陷入瘫痪(严格来说是所有从节点变成独立节点,再无关联性),直至人工重新指定新的主节点。
为了解决上面的问题,Redis 在 2.8 版本后开始支持哨兵模式,其架构模式如下图:
当主节点掉线后,会进行如下的过程,会从从节点中产生一个主节点,代替原来的主节点:
Redis 的Sentinel 系统(即哨兵系统)可用于管理多组 Redis 主从实例,它是Redis的高可用性解决方案。这个系统主要执行以下三个任务:
- 监控(Monitoring):Sentinel 会不断地定期检查主/从节点服务器是否运作正常
- 提醒(Notification):当被监控的某个节点服务器出现问题时,Sentinel 可以通过 API 向管理员或者其他应用程序发送通知
- 自动故障迁移(Automaticfailover):当一个主节点不能正常工作时,Sentinel 会开始一次自动故障迁移操作,它会将失效主节点下的其中一个从节点升级为新的主节点,并让失效主节点的其他从节点改为复制新的主节点。当 Redis 客户端试图连接失效的主节点时,集群也会向客户端返回新主节点的地址,使得集群可以使用新主节点代替失效主节点。
1.2部署
下面演示如何在上一阶段的主从模式基础上,增加部署一套哨兵系统。
先准备好三份配置文件:
角色 | 配置文件 | 监听端口 |
---|---|---|
哨兵 | sentinel-26380.conf | 26380 |
哨兵 | sentinel-26381.conf | 26381 |
哨兵 | sentinel-26382.conf | 26382 |
注: 这三份配置文件均拷贝自/usr/local/redis-ms/sentinel.conf ,拷贝到 /usr/local/redis-ms/ 目录再修即可。建议哨兵至少部署 3 个,并且哨兵节点数量要满足 2n+1(n>=1),即奇数个。
哨兵 sentinel-26380.conf 配置文件内容如下:
bind 127.0.0.1 # 正式部署请设为合适的 IP
port 26380
daemonize yes # 后台启动模式(若无配置项则添加)
dir /tmp/redis-ms # Redis 的工作目录(若不存在需手建否则无法启动),logfile 受其影响
logfile "sentinel-26380.log" # 哨兵日志名称(若无配置项则添加),正式部署请设置为合适的名称
sentinel monitor mymaster 127.0.0.1 6379 2 # 标注所监视的主机(其下的从机会被自动拉取,无需配置)
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
哨兵 sentinel-26381.conf 配置文件内容如下:
bind 127.0.0.1 # 正式部署请设为合适的 IP
port 26381
daemonize yes # 后台启动模式(若无配置项则添加)
dir /tmp/redis-ms # Redis 的工作目录(若不存在需手建否则无法启动),logfile 受其影响
logfile "sentinel-26381.log" # 哨兵日志名称(若无配置项则添加),正式部署请设置为合适的名称
sentinel monitor mymaster 127.0.0.1 6379 2 # 标注所监视的主机(其下的从机会被自动拉取,无需配置)
sentinel down-after-milliseconds exp-blog.com 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
哨兵 sentinel-26382.conf 配置文件内容如下:
bind 127.0.0.1 # 正式部署请设为合适的 IP
port 26382
daemonize yes # 后台启动模式(若无配置项则添加)
dir /tmp/redis-ms # Redis 的工作目录(若不存在需手建否则无法启动),logfile 受其影响
logfile "sentinel-26382.log" # 哨兵日志名称(若无配置项则添加),正式部署请设置为合适的名称
sentinel monitor exp-blog.com 127.0.0.1 6379 2 # 标注所监视的主机(其下的从机会被自动拉取,无需配置)
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
针对以上几个sentinel-xxxxx.conf 配置中的几个关键配置项说明如下:
sentinel monitor mymaster 127.0.0.1 6379 2
监控的主节点的名字为mymaster(这个名字任意的,有效字符为[A-Z] [a-z] [0-9] [._-])
监控的主节点服务地址 127.0.0.1:6379
行尾最后的 2 表示当集群中有 2 个以上 sentinel 认为主节点下线时,才认为其客观下线
sentinel down-after-milliseconds mymaster 30000
主节点在 30000 ms 内无反应,哨兵会开始使用“选举机制”进行主从切换
sentinel parallel-syncs mymaster 1
在因主节点失效而发生故障转移(即主从切换)时,这个参数决定了最多可以有多少个从节点同时对新的主节点进行并发同步。这个数字越小,完成故障转移所需的时间就越长(余下的从节点需要排队等待同步);但这个数字越大,就意味着越多的从节点因为正在对新的主节点进行同步而不可用。当从节点只用于查询服务时,可将此值设为 1 确保最多只有一个从节点因同步而不可用。
sentinel failover-timeout mymaster180000
如果在该 180000 ms 内未能完成故障转移,则认这次故障转移超时失败。
不过即使超时,从节点也会正确指向新主节点,但不会按照 parallel-syncs 规则进行同步
接下来就可以启动 Redis 主从服务和 Sentinel 系统了。
启动顺序必须严格按照:
Redis Master(主节点) -> Redis Slave(从节点) -> Redis Sentinel(哨兵节点)
主从服务的启动在上一阶段已经做过了,此处就不重启了。
Sentinel 系统需要使用 redis-sentinel
命令启动:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-sentinel ../sentinel-26380.conf # 启动 Redis 哨兵节点
./redis-sentinel ../sentinel-26381.conf # 启动 Redis 哨兵节点
./redis-sentinel ../sentinel-26382.conf # 启动 Redis 哨兵节点
1.3 测试
现在测试 Sentinel 系统是否能正常工作。
可先通过ps -ef|grep redis
命令可查看四个主从进程和三个监控进程是否正常启动:
然后通过 Redis 测试客户端命令 redis-cli 连接到任意一台 Sentinel 机器查看监控信息(实际生
产环境中,一般是不需要连接 Sentinel 机器的):
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-cli -h 127.0.0.1 -p 26380 # 连接到哨兵机 26380
127.0.0.1:26380> info sentinel # 查看监控信息
./redis-cli -h 127.0.0.1 -p 26381
127.0.0.1:26381> info sentinel
./redis-cli -h 127.0.0.1 -p 26382
127.0.0.1:26382> 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=3,sentinels=3
# 0 号主机名称为mymaster,地址为 127.0.0.1:6379,共有三台从机,三台哨兵机
现在尝试终止 Redis 主机进程(6379 端口节点)来模拟主机下线:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-cli -h 127.0.0.1 -p 6379 # 连接到 Redis 主机
127.0.0.1:6379> shutdown # 终止 Redis 服务
然后连接到任意一台哨兵机,查看当前的监控信息:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-cli -h 127.0.0.1 -p 26380 # 连接到哨兵机 26380
127.0.0.1:26380> 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:6382,slaves=3,sentinels=3 # 主机地址发生变化了
不难发现主机变成了 127.0.0.1:6382,登陆这台主机查看主从信息:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-cli -h 127.0.0.1 -p 6382 # 连接到 Redis 主机
127.0.0.1:6382> info replication # 查看主从信息
# 返回主从信息
# Replication
role:master #角色是主节点
connected_slaves:2 #其下有两个从节点
slave0:ip=127.0.0.1,port=6380,state=online,offset=106257,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=106124,lag=0
master_replid:199f376adf11c411e84584a320cd825fd48fd60e
master_replid2:e042fa1900358b32eaa4b84817642e04145c9c87
master_repl_offset:106523
second_repl_offset:88686
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:106523
由此可知,当原主机 6379 下线后,原从机 6382 被哨兵系统提升为新的主机,而其他的两台从机 6380 和 6381 变成新主机 6382 的从机。此时集群系统变成一主两从。
现在重新启动 6379 机器:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-server ../redis-6379.conf # 启动 Redis 机器
再登陆新主机 127.0.0.1:6382 查看主从信息:
cd /usr/local/redis-ms/src/ # 切换到启动脚本目录
./redis-cli -h 127.0.0.1 -p 6382 # 连接到 Redis 主机
127.0.0.1:6382> info replication # 查看主从信息
# 返回主从信息
# Replication
role:master #6382还是主节点
connected_slaves:3
slave0:ip=127.0.0.1,port=6380,state=online,offset=136282,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=136282,lag=1
slave2:ip=127.0.0.1,port=6379,state=online,offset=136282,lag=1 #重启后的6379并没有做回主节点,而是成为6382的从节点
master_replid:199f376adf11c411e84584a320cd825fd48fd60e
master_replid2:e042fa1900358b32eaa4b84817642e04145c9c87
master_repl_offset:136282
second_repl_offset:88686
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:136282
由此可知,当 6379 机器重新上线后,并不会恢复原主机的身份,而是被哨兵系统挂接到新主机 6382 下,成为其从机。此时集群系统重新变成一主三从。
至此 Redis 哨兵模式部署完成。
为了下面部署Redis集群,现在先停止前面部署的所有 Redis 进程:
#pkill redis
1.4哨兵模式一键启动/停止/重启脚本
此脚本是在本次实验的部署方式和位置为基础编写的,仅适用于 Redis 节点均在同一台机器的场景。若要在其他地方使用,需要根据实际情况进行修改。
#!/bin/bash
# 根据主从/哨兵模式的部署目录对应修改
cd /usr/local/redis-ms/src/
# 启动函数
start()
{
./redis-server ../redis-6379.conf &
./redis-server ../redis-6380.conf &
./redis-server ../redis-6381.conf &
./redis-server ../redis-6382.conf &
./redis-sentinel ../sentinel-26380.conf &
./redis-sentinel ../sentinel-26381.conf &
./redis-sentinel ../sentinel-26382.conf &
echo "all running"
}
# 停止函数
stop()
{
ps -ef | grep "redis" | grep -v "grep" |awk '{print $2}'| while read pid
do
C_PID=$(ps --no-heading $pid | wc -l)
if [[ $C_PID == "1" ]]; then
kill -9 $pid
echo "PID=$pid is dead"
else
echo "PID=$pid not exists"
fi
done
echo "all dead"
}
# 脚本入口参数 start|stop|restart
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
printf 'Usage: %s {start|stop|restart}\n'"$prog"
exit 1
;;
esac
这是 shell 脚本,保存为mss.sh(文件名任意)即可执行(若无法执行可能是换行符问题,可尝试通过 dos2unix 命令修正换行符)。
sh mss.sh start # 启动
sh mss.sh stop # 停止
sh mss.sh restart # 重启