Redis哨兵集群(Sentinel)介绍与实战部署

一、哨兵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
点赞

发表回复