Redis高可用方案之哨兵模式(Sentinel)

絮絮叨叨:Sentinel是基于主从复制的,大家在学习哨兵模式之前,应该具备主从复制的基础,可以阅读我的这篇文章:Redis主从复制 Replication

接下来正式进入正文,本文主要说明 Sentinel如何感知服务器,如何认定主服务器下线,以及如何选举新的主服务器过程。

目录

1  Sentinel主要工作流程

2  启动Sentinel

3  获取主服务器信息,感知从服务器

4  获取从服务器信息

5  感知其他sentinel

6  检查主观下线状态

7  检查客观下线状态

7.1  发送 SENTINEL is-master-down-by-addr 命令

7.2  接收 SENTINEL is-master-down-by-addr 命令

7.3  接收 SENTINEL is-master-down-by-addr 命令回复

8  选举领头sentinel

9  故障转移

9.1  选举新主服务器

 9.2  修改从服务器的复制目标

9.3  将旧的主服务器变为从服务器


1  Sentinel主要工作流程

Sentinel 哨兵是Redis的高可用解决方案:Sentinel系统是由一系列Sentinel实例组成的,负责监视任意多个主服务器,以及主服务器属下的所有从服务器。如下图,双环(sever1)的是主服务器,单环是主服务器从属的从服务器(server2、sever3、server4)

 当监察到主服务器下线:

 sentinel系统就会自动在从服务器中挑选一个升级为新的主服务器,代替已下线的旧主服务器,并让其他从服务器成为新主服务器的从服务器。

 当旧的主服务器上线后,降级为新的主服务器的从服务器

 这样,就实现了故障转移,实现高可用。接下来说一下实现细节。

2  启动Sentinel

启动一个sentinel的方法和启动一个服务器差不多。有2种方式启动:

# 第一种
redis-sentinel  /path/to/sentinel.conf

# 第二种
redis-server /path/to/sentinel.conf --sentinel

主要配置项有:

# 启动端口号
port 26379 
 
# mymaster:  主服务器名(就是一个别名,任意取,但是必须唯一不能重复,可以同时监视任意多个主服务器)
# 10.0.2.39: 主服务器IP
# 6379:      主服务器端口
# 2:         超过2个哨兵认为服务器主观下线,那么则可以认为这个服务器客观下线
sentinel monitor mymaster 10.0.2.39 6379 2

# mymaster 服务器超过30秒没有心跳,则认为主观下线
sentinel down-after-milliseconds mymaster 30000

# ....更多可以查看redis官网描述

启动后,sentinel将会做一系列初始化工作,其中包括根据配置文件,初始化监视的主服务器列表,并且建立连接。

比如有两个服务器 master1 和 master2 配置如下:

 sentinel 自身状态结构 sentinelState 有一个字典masters 专门用于保存监视的主服务器列表,其中masters字典的键为对应配置的主服务器别名,值为sentinelInstance结构,保存IP,端口等信息。

随后,sentinel会与每个被监视的主服务器创建2条异步网络连接:

  • 有个是命令链接,用户向主服务器发送命令,并接收回复
  • 一个是订阅链接,用户订阅主服务器的 __sentinel__:hello 频道

3  获取主服务器信息,感知从服务器

sentinel与masters字典中保存的主服务器建立连接后,会以每10秒一次的频率向主服务器发送INFO命令,获取主服务器的信息

 如果主服务器master有3个从服务器slave0,slave1,slave2,那么sentinel将会收到master1的回复

 分析上面内容,可以获取如下信息:

  • 获取主服务器运行id,以及角色
  • 获取主服务器从属的从服务器信息,包括IP地址和端口号,这样sentinel无须用户提供从服务器的地址信息就可以自动发现从服务器

根据主服务器返回的slaves信息,sentinel将会用于更新主服务器实例结构的slaves字典,该字典记录了对应了主服务器属下的所有从服务器名单:

 

字典记录了对应了主服务器属下的所有从服务器名单:

  • 字典的键由 ip:port 组成,对于 127.0.0.1 和 11111 的从服务器来说,则是 127.0.0.1:11111;
  • 字典的值则是从服务器对应的实例结构;sentinel在分析INFO命令返回包含的从服务器信息时,会检查是否已存在slaves字典中,如果存在则继续更新,否则创建。

4  获取从服务器信息

sentinel发现主服务器出现新的从服务器时,不仅会创建对应的实例结构,还会创建连接到从服务器的命令连接和订阅连接,和主服务器的操作一样。

 和主服务器一样,sentinel同样以每10秒1次的频率向从服务器发送INFO命令,获取从服务器的信息,并获得类似回复

 可以通过INFO命令回复提取到以下信息:

  • 从服务器的运行id和角色  (用于后续选举新主服务器用)
  • 从服务器的IP地址和端口
  • 从服务器的优先级 slave_priority   (用于后续选举新主服务器用)
  • 从服务器的复制偏移量 slave_repl_offset  (用于后续选举新主服务器用)

根据这些信息,更新从服务器的实例结构,例如:

 

5  感知其他sentinel

回忆一下,sentinel除了和主、从服务器建立命令连接,另外还建立了订阅连接,主要作用就是用来发现、更新其他sentinel信息,以及更新被监视的服务器的认知。

默认情况下,sentinel每2秒一次向主、从服务器发布一次消息,如果sentinel正在监视的是主服务器那么m_就是master的信息,如果是从服务器,那么就是从服务器的信息。

PUSHLISH __sentinel__:hello "sentinel_ip" 
                            "sentinel_port" 
                            "sentinel_runid"  
                            "sentinel_epoch"
                            "m_name" 
                            "m_ip" 
                            "m_port" 
                            "m_epoch"

如这条实例表示:

  • sentinel IP为127.0.0.1,端口号为26379,运行ID为e955,当前配置纪元为0
  • 主服务器名为 mymaster,IP为127.0.0.1,端口号为6379,当前配置纪元为0

 对于监视同一个服务器的其他sentinel来说,也会接收到这条消息,如此其他sentinel就可以感知到有其他sentinel的存在,并保存下来。

如有3个sentinel组成sentinel系统,sentinel1,sentinel2,sentinel3,正在监视同一个服务器,那么当sentinel1向服务器 __sentinel__:hello 发送一条消息时,sentinel2和sentinel3还有sentinel1自己也都会接收到这条消息。

 

当sentinel从__sentinel__:hello中接收到一条消息时,可以从消息中提取到发送这条消息的源sentinel地址,sentinel端口号,运行ID等参数,并进行检查:

  • 检查运行ID,如果和自己的相同,则说明是自己发送的,丢弃
  • 反之,如果和自己的运行ID不一样,说明是正在监视同一服务器的其他sentinel发送过来的,接收信息的sentinel根据这些参数对主服务器的实例结构进行更新。

如三个sentinel正在监视主服务器mymaster,那么当sentinel 127.0.0.1:26379接收到以下信息时

将执行以下操作:

  • 识别到 127.0.0.1:26379是自己,丢弃;
  • 识别到 127.0.0.1:26380, 127.0.0.1:26381,根据提取的信息保存在sentinels字典中; 

如sentinel1 127.0.0.1:26379 监视的主服务器mymaster对应数据结构如下

 这样,sentinel系统就通过 __sentinel__:hello 频道实现了互相发现的功能。随后,sentinel会向发现的其他sentinel建立一条命令连接,用户发送命令给其他sentinel,并且接受响应。

需要注意的是,sentinel和sentinel之间只会创建命令连接,不会创建订阅连接,因为订阅连接主要用来发现其他sentinel,只要和主从服务器之间创建就可以实现该功能,所以没有必要。

6  检查主观下线状态

回顾以下前面的配置项

# mymaster 服务器超过30秒没有心跳,则认为主观下线
sentinel down-after-milliseconds mymaster 30000

 默认情况下,sentinel会每秒1次向所有和它创建了连接的实例(主服务器,从服务器,其他sentinel)发送PING连接,并通过实例返回的内容判断是否在线:

  • 有效回复:PONG、LOADING、MASTERDOWN
  • 无效回复:除了有效回复外的其他回复

如果在配置项 down-after-milliseconds 规定的时间内,如30秒,连续回复返回无效回复,那么sentinel会认为这个实例已经下线,即【主观下线】,需要注意的是,不同sentinel使用的配置文件不同,有可能出现sentinel1认为mymaster下线了,但是sentinel2认为还没有下线。

所以【主观下线】状态并不是最终的状态,还需要跟其他sentinel发起投票。

7  检查客观下线状态

当认为sentinel认为某服务器主观下线后,需要继续向其他sentinel询问,是否也认为该服务器已下线,如果满足配置项 monitor 的数量,那么则认为该服务器客观下线,进行下一步故障转移操作。

# mymaster:  主服务器名(就是一个别名,任意取,但是必须唯一不能重复,可以同时监视任意多个主服务器)
# 10.0.2.39: 主服务器IP
# 6379:      主服务器端口
# 2:         超过2个哨兵认为服务器主观下线,那么则可以认为这个服务器客观下线
sentinel monitor mymaster 10.0.2.39 6379 2

7.1  发送 SENTINEL is-master-down-by-addr 命令

sentinel认为主服务器主观下线后,会使用

 SENTINEL is-master-down-by-addr ip port current_epoch runid
  • current_port:表示当前配置的纪元,可以当作一个计数器,没什么特别意义
  • runid: 表示sentinel运行ID,询问阶段时值为*,选举零头sentinel时,值为零头sentinel的id

例如,被sentinel认为下线的主服务器ip为127.0.0.1,端口为6379,当前配置纪元为0,那么它将会向其他sentinel发送一条消息:

7.2  接收 SENTINEL is-master-down-by-addr 命令

其他sentinel接收到这条消息,则会检查这个服务器是否确实已经下线了(同样根据配置项down-after-milliseconds),随后回复源sentinel

  • down_state: 返回检查结果,1代表已下线,0代表未下线
  • leader_runid: 投票阶段值为*,选举阶段值为局部领头sentinel id
  • leader_epoch: 局部领头的配置纪元号,只有当leader_runid的值不为*时有效

1) 1
2) *
3) 0

说明该sentinel同意该主机已下线

7.3  接收 SENTINEL is-master-down-by-addr 命令回复

源sentinel根据其他sentinel返回的结果统计,如果满足客观下线需要的数量时,则进行下一步故障转移工作。注意,每个sentinel客观下线需要的票数不同,因为它们可能由不同配置文件启动的,主要由配置项决定。

# mymaster:  主服务器名(就是一个别名,任意取,但是必须唯一不能重复,可以同时监视任意多个主服务器)
# 10.0.2.39: 主服务器IP
# 6379:      主服务器端口
# 2:         超过2个哨兵认为服务器主观下线,那么则可以认为这个服务器客观下线
sentinel monitor mymaster 10.0.2.39 6379 2

8  选举领头sentinel

当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个sentinel会进行协商,选举一个领头,并由领头来进行下一步故障转移操作。

选举算法如下:在同一个配置纪元里,每个sentinel有发起让其他sentinel选择自己的权力,每个sentinel都有可能被选举为局部leader,规则是先到先得,最先向目标sentinel发送设置要求的源sentinel成为目标sentinel的局部leader,之后的所有请求都会被目标sentinel拒绝。如果某个sentinel被半数以上的sentinel设置为局部leader,那么它就是这个纪元中的唯一leader,有且只有一个。如果选举失败,那么继续下一个纪元的选举,直到选出leader为止。

9  故障转移

当选举完局部sentinel leader后,sentinel leader将会对已下线的主服务器进行故障转移操作,包括三个步骤:

  1. 在已下线的主服务器从属的从服务器中,选出一个从服务器,并转换为主服务器
  2. 让已下线的主服务器从属的从服务器,全部改为复制新选出来的主服务器
  3. 让已下线的主服务器上线后,改为新主服务器的从服务器。

9.1  选举新主服务器

选举新主服务器将会从下面条件中选择,权重从高到低:

  • 首先,选择优先级高的从服务器,对应配置项 replica-priority 
# The replica priority is an integer number published by Redis in the INFO
# output. It is used by Redis Sentinel in order to select a replica to promote
# into a master if the master is no longer working correctly.
#
# A replica with a low priority number is considered better for promotion, so
# for instance if there are three replicas with priority 10, 100, 25 Sentinel
# will pick the one with priority 10, that is the lowest.
#
# However a special priority of 0 marks the replica as not able to perform the
# role of master, so a replica with priority of 0 will never be selected by
# Redis Sentinel for promotion.
#
# By default the priority is 100.
replica-priority 100
  • 其次选择复制偏移量大的从服务器;
  • 最后选择运行id小的从服务器

选举出新的主服务器后,sentinel会发送slaveof no one命令给被选中的服务器,然后每秒一次的频率发送INFO命令(平时是每10秒1次),观察新主服务器的role等信息,当被升级的服务器role由slave变成master时,则说明顺利升级了。

 9.2  修改从服务器的复制目标

下一步,让已下线的主服务器从属的从服务器,全部改为复制新选出来的主服务器。通过发送slaveof 指令。 

下图展示了此时各个服务器的状态

9.3  将旧的主服务器变为从服务器

最后一步,让已下线的主服务器上线后,改为新主服务器的从服务器。通过发送slaveof指令。

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值