由于无法进行主动恢复,因此主从模式衍生出了哨兵模式。哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。Redis Sentinel是社区版本推出的原生高可用解决方案,Redis Sentinel部署架构主要包括两部分:Redis Sentinel集群和Redis数据集群,其中Redis Sentinel集群是由若干Sentinel节点组成的分布式集群,可以实现故障发现、故障自动转移、配置中心和客户端通知。Redis Sentinel的节点数量要满足2n+1(n>=1)的奇数个。
故障转移挑选新master的原则:
挑选好新的master节点后,Sentinel 向 新master发送 slaveof no one 指令,向其他的slave发送
slaveof [新master的IP] [新master的端口]
在哨兵模式架构中,client端在首次访问Redis服务时,实际上访问的是哨兵(sentinel),sentinel会将自己监控的Redis实例的master节点信息返回给client端,client后续就会直接访问Redis的master节点,并不是每次都从哨兵处获取master节点的信息。
sentinel会实时监控所有的Redis实例是否可用,当监控到Redis的master节点发生故障后,会从剩余的slave节点中选举出一个作为新的master节点提供服务,并将新master节点的地址通知给client端,其他的slave节点会通过slaveof命令重新挂载到新的master节点下。当原来的master节点恢复后,也会作为slave节点挂在新的master节点下。如下图:
一般情况下,为了保证高可用,sentinel也会进行集群部署,防止单节点sentinel挂掉。当sentinel集群部署时,各sentinel除了监控redis实例外,还会彼此进行监控。如下图:
要实现Redis节点的监控,sentinel首先要得到所有的Redis节点的信息。sentinel通过在配置文件中配置 sentinel monitor 选项来指定要监控的redis master节点的地址,然后在启动sentinel时,会创建与redis master节点的连接并向master节点发送一个info命令,master节点在收到info命令后,会将自身节点的信息和自己下面所有的slave节点的信息返回给sentinel,sentinel收到反馈后,会与新的slave节点创建连接,接下来就会每隔10秒钟向所有的redis节点发送info命令来获取最新的redis主从结构信息。
有了redis实例的主从信息后,sentinel就会以每秒钟一次的频率向所有redis实例发送一个PING命令,而且如果sentinel是集群部署的话,每个sentinel还会以同样的频率向其他sentinel实例发送PING命令。当redis实例和sentinel实例收到PING命令后,会向sentinel返回一个有效的回复:+PONG 、-LOADING 或者 -MASTERDOWN,若返回其他的回复,或者在指定时间内(sentinel down-after-milliseconds 选项配置)没有回复,那么sentinel认为实例的回复无效。如果实例在 sentinel down-after-milliseconds 时间内未返回过一次有效的回复,那该实例就会被sentinel标记为主观下线(Subjectively Down,简称 SDOWN,指的是单个 sentinel 实例对服务节点做出的下线判断)。
当redis master节点被足够数量(sentinel monitor 选项配置,其中的quorum即为指定的sentinel数量,下面会详细介绍相关参数)的sentinel标记为主观下线后,那么master节点就会被标记为客观下线(Objectively Down,简称 ODOWN,指的是多个 sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。【一个 sentinel 可以通过向另一个 sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线】)。客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例,sentinel 在将它们判断为下线前不需要进行协商, 所以slave服务器或者其他 sentinel 永远不会达到客观下线条件。
当redis master被标记为客观下线时,每个sentinel向其他slave节点发送info命令的频率由之前的10秒钟一次变为1秒钟一次。并且会通过raft算法在sentinel中选出一个leader,由leader节点完成redis的故障转移工作。
概念:主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
如果一个 redis 服务器没有在 master-down-after-milliseconds 选项所指定的时间内,对向它发送 PING 命令的 Sentinel 返回一个有效回复, 那么Sentinel 就会将这个服务器标记为主观下线。
单个Sentine判断Redis服务器主观下线之后,会通过提醒(流言传播(Gossip))告知其他的Sentinel服务器,其他的Sentinel就来围观这台Redis服务器,超过半数的Sentinel认为Redis主管下线后,则该Redis服务器的状态变为客观下线。
概念:多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断ODOWN。 (一个Sentinel 可以通过向另一个 Sentinel 发送命令来询问对方是否认为给定的服务器已下线)。
客观下线条件只适用于主服务器,对于其他类型的 Redis 实例, Sentinel在将它们判断为下线前不不需要进行协商, 所以从服务器或者其他Sentinel 不会达到客观下线条件。 只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个Sentinel就可能会被其他 Sentinel 推选出,并对失效的主服务器执行自动故障迁移操作。
在redis安装目录下,除了有redis本身的一个配置文件外,还有一个sentinel.conf,该文件就是sentinel的配置文件。在该文件中,主要有以下几个配置:
哨兵认为master客观下线后,故障恢复的操作需要由选举的领头哨兵来执行,选举采用Raft算法:
选出领头哨兵后,领头者开始对系统进行故障恢复,从出现故障的master的从数据库中挑选一个来当选新的master,选择规则如下:
哨兵模式基于前面的主从复制模式。哨兵的配置文件为Redis安装目录下的sentinel.conf文件,在文件中配置如下配置文件:
port 26379 # 哨兵端口
# mymaster定义一个master数据库的名称,后面是master的ip, port,1表示至少需要一个Sentinel进程同意才能将master判断为失效,如果不满足这个条件,则自动故障转移(failover)不会执行
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster 123456 # master的密码
sentinel down-after-milliseconds mymaster 5000 #5s未回复PING,则认为master主观下线,默认为30s
# 指定在执行故障转移时,最多可以有多少个slave实例在同步新的master实例,在slave实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
sentinel parallel-syncs mymaster 2
# 如果在该时间(ms)内未能完成故障转移操作,则认为故障转移失败,生产环境需要根据数据量设置该值
sentinel failover-timeout mymaster 300000
daemonize yes #用来指定redis是否要用守护线程的方式启动,默认为no
#保护模式如果开启只接受回环地址的ipv4和ipv6地址链接,拒绝外部链接,而且正常应该配置多个哨兵,避免一个哨兵出现独裁情况
#如果配置多个哨兵那如果开启也会拒绝其他sentinel的连接。导致哨兵配置无法生效
protected-mode no
logfile "/data/redis/logs/sentinel.log" #指明日志文件
其中daemonize的值yes和no的区别为:
然后就是启动哨兵,启动方式有两种,先进入Redis安装根目录下的bin目录,然后执行:
/server-sentinel ../sentinel.conf &
# 或者
redis-server sentinel.conf --sentinel
执行后可以看到有哨兵进程已启动,如下:
192:bin houjing$ ps -ef |grep redis
501 41115 1 0 11:37下午 ?? 0:12.00 ./redis-server 127.0.0.1:6379
501 41121 1 0 11:38下午 ?? 0:11.88 ./redis-server 127.0.0.1:6380
501 41621 1 0 3:53上午 ?? 0:00.04 ./redis-server *:26379 [sentinel]
可以多个哨兵监控一个master数据库,只需按上述配置添加多套sentinel.conf配置文件,比如分别为sentinel1.conf、sentinel2.conf、sentinel3.conf,分别以26379,36379,46379端口启动三个sentinel,此时就成功配置多个哨兵,成功部署了一套3个哨兵、一个master、2个slave的Redis集群。
我们通过手动杀掉master节点进行测试,然后看slave节点是否会自动晋升为master节点:
192:bin houjing$ kill -9 41115
192:bin houjing$ ps -ef |grep redis
501 41121 1 0 11:38下午 ?? 0:12.33 ./redis-server 127.0.0.1:6380
501 41621 1 0 3:53上午 ?? 0:00.68 ./redis-server *:26379 [sentinel]
127.0.0.1:6379> info replication
Could not connect to Redis at 127.0.0.1:6379: Connection refused
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:14604
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:85362a9182cf9a48d1f93b0633e1963b583c30f7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14604
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14604
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_replid:36bf84c3cb3f2b7969040fdcce9a962025be3605
master_replid2:85362a9182cf9a48d1f93b0633e1963b583c30f7
master_repl_offset:16916
second_repl_offset:15963
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:16916
可以看到验证成功,然后我们重启原先宕机的master节点,可以看到原先的节点成功启动,并由master变成了slave节点,如下所示:
-cli -p 6380
192:bin houjing$ ./redis-server ../redis.conf &
[1] 41640
192:bin houjing$ 41640:C 07 Apr 2020 03:59:05.475 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
41640:C 07 Apr 2020 03:59:05.475 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=41640, just started
41640:C 07 Apr 2020 03:59:05.475 # Configuration loaded
[1]+ Done ./redis-server ../redis.conf
192:bin houjing$ ps -ef |grep redis
501 41121 1 0 11:38下午 ?? 0:12.82 ./redis-server 127.0.0.1:6380
501 41621 1 0 3:53上午 ?? 0:01.49 ./redis-server *:26379 [sentinel]
501 41641 1 0 3:59上午 ?? 0:00.02 ./redis-server 127.0.0.1:6379
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:29056
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:36bf84c3cb3f2b7969040fdcce9a962025be3605
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:29056
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:28488
repl_backlog_histlen:569
以上就完成了对哨兵部署方式的测试。
运维:终于不用再背着数万实例的Redis集群了!_Cluster
Redis学习之4种模式实践及机制解析(单机、主从、哨兵、集群)
redis架构_剑八-的博客-CSDN博客
Redis高可用方案—主从(masterslave)架构
Redis高可用架构—哨兵(sentinel)机制详细介绍
Redis高可用架构—Redis集群(Redis Cluster)详细介绍
Redis学习之Redis集群模式缺陷及其处理