一、哨兵sentinel简介
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-Slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
Sentinel功能
- 监控(Monitoring)
Sentinel会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification)
当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover)
当一个主服务器不能正常工作时,Sentinel会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。
主观下线和客观下线
- 主观下线:
Subjectively Down,简称 SDOWN,指的是单个 Sentinel 实例对服务器做出的下线判断。
- 客观下线:
Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断。
故障转移FAILOVER
- 1.发现主服务器已经进入客观下线状态。
- 2.基于Raft leader election协议,进行投票选举
- 3.如果当选失败,那么在设定的故障迁移超时时间的两倍之后,重新尝试当选。如果当选成功,那么执行以下步骤。
- 4.选出一个从服务器,并将它升级为主服务器。
- 5.向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。
- 6.通过发布与订阅功能,将更新后的配置传播给所有其他Sentinel,其他Sentinel对它们自己的配置进行更新。
- 7.向已下线主服务器的从服务器发送SLAVEOF命令,让它们去复制新的主服务器。
- 8.当所有从服务器都已经开始复制新的主服务器时, leader Sentinel 终止这次故障迁移操作。
注意:每当一个Redis实例被重新配置(reconfigured)—— 无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 —— Sentinel 都会向被重新配置的实例发送一个CONFIG REWRITE命令,从而确保这些配置会持久化在硬盘里。
Sentinel选择主库的规则
- 在失效主服务器属下的从服务器当中,那些被标记为主观下线、已断线、或者最后一次回复PING命令的时间大于五秒钟的从服务器都会被淘汰。
- 在失效主服务器属下的从服务器当中,那些与失效主服务器连接断开的时长超过down-after选项指定的时长十倍的从服务器都会被淘汰。
- 在经历了以上两轮淘汰之后剩下来的从服务器中,我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器;如果复制偏移量不可用,或者从服务器的复制偏移量相同,那么带有最小运行ID的那个从服务器成为新的主服务器。
Sentinel自动故障迁移的一致性特质
- Sentinel自动故障迁移使用Raft算法来选举领头(leader)Sentinel ,从而确保在一个给定的周期(epoch)里,只有一个领头产生。
- 这表示在同一个周期中, 不会有两个 Sentinel 同时被选中为领头,并且各个 Sentinel 在同一个节点中只会对一个领头进行投票。
- 更高的配置节点总是优于较低的节点,因此每个 Sentinel 都会主动使用更新的节点来代替自己的配置。
简单来说,我们可以将Sentinel配置看作是一个带有版本号的状态。一个状态会以最后写入者胜出(last-write-wins)的方式(也即是,最新的配置总是胜出)传播至所有其他Sentinel。
二、Redis哨兵(Sentinel)部署
服务器环境
主机名 | IP | 角色 |
---|---|---|
redis-01 | 172.16.1.56 | master |
redis-02 | 172.16.1.57 | slave |
redis-03 | 172.16.1.58 | slave |
配置主从环境
在做sentinel之前,需要先部署好redis的主从环境。
Redis主从复制详细请阅读上篇博文:https://www.wanhebin.com/database/redis/768.html
- 在redis02、redis03(slave)上执行 SLAVEOF 命令,开启主从
127.0.0.1:6379> slaveof 172.16.1.56 6379
OK
- 查看主库和从库的主从复制状态
redis-01:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.16.1.57,port=6379,state=online,offset=8191,lag=0
slave1:ip=172.16.1.58,port=6379,state=online,offset=8191,lag=0
master_repl_offset:8191
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8190
redis-02:
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.16.1.56
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:8471
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_acklog_histlen:0
配置Sentinel
这里以单哨兵为例。
- 创建sentinel工作目录
[root@redis-03 ~]# mkdir -p /service/redis/26379
- 编写sentinel配置文件
[root@redis-03 ~]# vim /service/redis/26379/sentinel.conf
bind 172.16.1.58 127.0.0.1
port 26379
daemonize yes
logfile "/service/redis/26379/sentinel.log"
dir "/service/redis/26379"
#定义Redis主库的地址与端口,名称为mymaster,(名称可以自定义),1代表是只要有1台sentinel认为主库宕机,那就切换
sentinel monitor mymaster 172.16.1.56 6379 1
#定义5000毫秒联系不上mymaster主库,就认为主库宕机了
sentinel down-after-milliseconds mymaster 5000
#定义自动故障切换超时时间为3分钟
sentinel failover-timeout mymaster 180000
#设置只有1个从库处于不能处理命令请求的状态
sentinel parallel-syncs mymaster 1
注意:如果redis配置了密码,sentinel配置中必须配置认证sentinel auth-pass <master-name> <password>
,否则不能自动切换。
- 启动sentinel
[root@redis-03 ~]# redis-sentinel /service/redis/26379/sentinel.conf
关闭命令为redis-cli -p 26379 shutdown
- 查看进程,检查sentinel是否启动
[root@redis-03 ~]# netstat -tln | grep 26379
tcp 0 0 127.0.0.1:26379 0.0.0.0:* LISTEN
tcp 0 0 172.16.1.58:26379 0.0.0.0:* LISTEN
- 再次查看sentinel的配置文件
发现配置文件发生了一些变化
多出了2个redis从库redils-02、redis-03等。也就是sentinel已经监控上整个redis复制架构了。
[root@redis-03 ~]# cat /service/redis/26379/sentinel.conf
bind 172.16.1.58 127.0.0.1
port 26379
daemonize yes
logfile "/service/redis/26379/sentinel.log"
dir "/service/redis/26379"
sentinel myid 6ef0e8e9af12118fdb0d787290712e3ffe342118
sentinel monitor mymaster 172.16.1.56 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel config-epoch mymaster 0
# Generated by CONFIG REWRITE
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 172.16.1.57 6379
sentinel known-slave mymaster 172.16.1.58 6379
sentinel current-epoch 0
Sentinel切换测试
- 停止主库
[root@redis-01 ~]# redis-cli shutdown
- 查看原从库redis-02的主从状态信息
127.0.0.1:6379> info replication
# Replication
role:master #由此可见,原从库redis-02已经被提升为主库
connected_slaves:1
slave0:ip=172.16.1.58,port=6379,state=online,offset=8563,lag=0 #它的从库为redis-03
master_repl_offset:8700
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8699
- 重新开启旧的主库redis-01,并查看主从状态信息
[root@redis-01 ~]# redis-server /service/redis/6379/redis.conf
[root@redis-01 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave #角色变成了slave
master_host:172.16.1.57 #主库的为redis-02
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:14452
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
- 在新主redis-02上查看主从信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.16.1.58,port=6379,state=online,offset=29282,lag=1
slave1:ip=172.16.1.56,port=6379,state=online,offset=29282,lag=1 #redis-01自动加入了集群
master_repl_offset:29282
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:29281
三、Sentinel配置参数和常用命令
Sentinel常用命令
- 连接sentinel管理端口
[root@redis-03]# redis-cli -p 26379
- 检测状态,返回PONG
127.0.0.1:26379> PING
PONG
- 列出所有被监视的主服务器
127.0.0.1:26379> SENTINEL masters
- 列出所有被监视的从服务器
127.0.0.1:26379> SENTINEL slaves mymaster
- 返回给定名字的主服务器的IP地址和端口号
127.0.0.1:26380> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"
- 重置所有名字和给定模式
127.0.0.1:26380> SENTINEL reset mymaster
- 当主服务器失效时,在不询问其他Sentinel意见的情况下,强制开始一次自动故障迁移。
127.0.0.1:26380> SENTINEL failover mymaster
若把想要优先提升为主库以外的库,需要把其优先级调低。命令config set slave-priority 0
sentinel配置参数详解:
sentinel monitor <master-name> <ip> <port> <quorum>
告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效。
#配置示例:
sentinel monitor mymaster 172.16.1.56 6379 1
sentinel down-after-milliseconds <master-name> <times>
指定了Sentinel认为服务器已经断线所需的毫秒数。如果服务器在给定的毫秒数之内,没有返回Sentinel发送的Ping命令的回复,或者返回一个错误,那么Sentinel将这个服务器标记为主观下线(subjectively down,简称SDOWN)。不过只有一个Sentinel将服务器标记为主观下线并不一定会引起服务器的自动故障迁移:只有在足够数量的Sentinel都将一个服务器标记为主观下线之后,服务器才会被标记为客观下线(objectively down, 简称 ODOWN ),这时自动故障迁移才会执行。
#配置示例:
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout <master-name> <times>
当进行自动故障切换时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
#配置示例
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs <master-name> <nums>
在发生failover主备切换时,这个选项指定了最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态。
#配置示例:
sentinel parallel-syncs mymaster 1
sentinel auth-pass <master-name> <password>
如果主节点有密码,需要配置密码,防止无法获取主节点信息。注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
#配置示例:
sentinel auth-pass mymaster 123456
sentinel notification-script <master-name> <script-path>
当有重要事件,例如客观下线,主观下线时,将执行指定的脚本,并将一些相关参数传进去,可以发送邮件来通知。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#配置示例:
sentinel notification-script mymaster /var/redis/notify.sh
sentinel client-reconfig-script <master-name> <script-path>
当故障转移结束后触发的脚本,并将一些相关参数传进去。
#配置示例:
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh