|
|
51CTO旗下网站
|
|
移动端

分布式Redis深度历险-Sentinel

试想下,在一主一从或一主多从的结构下,如果主服务器挂了,整个集群就不可用了,单点问题并没有解决。Redis使用Sentinel解决该问题,保障集群的高可用。

作者:酋长的Java架构笔记来源:酋长的Java架构笔记|2019-07-22 09:35

试想下,在一主一从或一主多从的结构下,如果主服务器挂了,整个集群就不可用了,单点问题并没有解决。Redis使用Sentinel解决该问题,保障集群的高可用。

如何保障集群高可用

保障集群高可用,要具备如下能力:

  • 能监测服务器的状态,当主服务器不可用时,能及时发现
  • 当主服务器不可用时,选择一台最合适的从服务器替代原有主服务器
  • 存储相同数据的主服务器同一时刻只有一台

要实现上述功能,最直观的做法就是,使用一台监控服务器来监视Redis

服务器的状态。

分布式Redis深度历险-Sentinel

监控服务器和主从服务器间维护一个心跳连接,当超出一定时间没有收到主服务器心跳时,主服务器就会被标记为下线,然后通知从服务器上线成为主服务器。

分布式Redis深度历险-Sentinel

当原来的主服务器上线后,监控服务器会将其转换为从服务器。

分布式Redis深度历险-Sentinel

按照上述流程似乎解决了集群高可用的问题,但似乎有哪里不对:如果监控服务器出了问题怎么办?我们可以在加上一个从监控服务器,当主服务器不可用的时候顶上。

分布式Redis深度历险-Sentinel

但问题是谁来监控’监控服务器’呢?子子孙孙无穷尽也。。

先把疑问放在一旁,先来看下Redis Sentinel集群的实现

Sentinel

和上一小节的想法一样,Redis通过增加额外的Sentinel服务器来监控数据服务器,Sentinel会与所有的主服务器和从服务器保存连接,用以监听服务器状态以及向服务器下达命令。

分布式Redis深度历险-Sentinel

Sentinel本身是一个特殊状态的Redis服务器,启动命令:

redis-server /xxx/sentinel.conf --sentinel,sentinel模式下的启动流程与普通redis server是不一样的,比如说不会去加载RDB文件以及AOF文件,本身也不会存储业务数据。

与主服务器建立连接

Sentinel启动后,会与配置文件中提供的所有主服务器建立两个连接,一个是命令连接,一个是订阅连接。

命令连接用于向服务器发送命令。

订阅连接则是用于订阅服务器的_sentinel_:hello频道,用于获取其他Sentinel信息,下文会详细说。

获取主服务器信息

Sentinel会以一定频率向主服务器发送Info命令获取信息,包括主服务器自身的信息比如说服务器id等,以及对应的从服务器信息,包括ip和port。Sentinel会根据info命令返回的信息更新自己保存的服务器信息,并会与从服务器建立连接。

获取从服务器信息

与和主服务器的交互相似,Sentinel也会以一定频率通过Info命令获取从服务器信息,包括:从服务器ID,从服务器与主服务器的连接状态,从服务器的优先级,从服务器的复制偏移等等。

向服务器订阅和发布消息

在如何保障集群高可用小节留下了一个疑问:用如何保证监视服务器的高可用? 在这里我们可以先给出简单回答:用一个监视服务器集群(也就是Sentinel集群)。如何实现,如何保证监视服务器的一致性暂且先不说,我们只要记住需要用若干台Sentinel来保障高可用,那一个Sentinel是如何感知其他的Sentinel的呢?

前面说过,Sentinel在与服务器建立连接时,会建立两个连接,其中一个是订阅连接。Sentinel会定时的通过订阅连接向_sentinel_:hello频道频道发送消息(对Redis发布订阅功能不太了解的同学可以去去了解下),其中包括:

  • Sentinel本身的信息,如ip地址、端口号、配置纪元(见下文)等
  • Sentinel监视的主服务器的信息,包括ip、端口、配置纪元(见下文)等

同时,Sentinel也会订阅_sentinel_:hello频道的消息,也就是说Sentinel即向该频道发布消息,又从该频道订阅消息。

分布式Redis深度历险-Sentinel

Sentinel有一个字典对象sentinels,保存着监视同一主服务器的其他所有Sentinel服务器,当一个Sentinel接收到来自_sentinel_:hello频道的消息时,会先比较发送该消息的是不是自己,如果是则忽略,否则将更新sentinels中的内容,并对新的Sentinel建立连接。

主观下线

Sentinel默认会以每秒一次的频率向所有建立连接的服务器(主服务器,从服务器,Sentinel服务器)发送PING命令,如果在down-after-milliseconds内都没有收到有效回复,Sentinel会将该服务器标记为主观下线,代表该Sentinel认为这台服务器已经下线了。需要注意的是不同Sentinel的down-after-milliseconds是可以不同的。

客观下线

为了确保服务器真的已经下线,当Sentinel将某个服务器标记为主观下线后,它会向其他的Sentinel实例发送Sentinel is-master-down-by-addr命令,接收到该命令的Sentinel实例会回复主服务器的状态,代表该Sentinel对该主服务器的连接情况。

Sentinel会统计发出的所有Sentinel is-master-down-by-addr命令的回复,并统计同意将主服务器下线的数量,如果该数量超出了某个阈值,就会将该主服务器标记为客观下线。

选举领头Sentinel

当Sentinel将一个主服务器标记为客观下线后,监视该服务器的各个Sentinel会通过Raft算法进行协商,选举出一个领头的Sentinel。

建议你先看Raft算法的基础知识,再来看下文。

规则:

所有的Sentinel都有可能成为领头Sentinel的资格

每次选举后,无论有没有选出领头Sentinel,配置纪元都会+1

在某个纪元里,每个Sentinel都有为投票的机会

我们称要求其他人选举自己的Sentinel称为源Sentinel,将被要求投票的Sentinel称为目标Sentinel

每个发现主服务器被标记为客观下线且还没有被其他Sentinel要求投票的Sentinel都会要求其他Sentinel将自己设置为头

目标Sentinel在一个配置纪元里,一旦为某个Sentinel(也可能是它自己)投票后,对于之后收到的要求投票的命令,将拒绝

目标Sentinel对于要求投票的命令将回复自己选举的Sentinel的id以及当前配置纪元

源Sentinel在接收到要求投票的回复后:如果回复的配置纪元与自己的相同,则再检测目标Sentinel选举的头Sentinel是不是自己

如果某个Sentinel被半数以上的Sentinel设置成了领头Sentinel,那它将称为领头Sentinel

一个配置纪元只会选出一个头(因为一个头需要半数以上的支持)

如果在给定时间内,还没有选出头,则过段时间再次选举(配置纪元会+1)

还记得我们在文章开头提出的如何保证Redis服务器高可用的问题吗?

答案就是使用若干台Sentinel服务器,通过Raft一致性算法来保障集群的高可用,只要Sentinel服务器有一半以上的节点都正常,那集群就是可用的。

故障转移

领头Sentinel将会进行以下3个步骤进行故障转移:

1.在已下线主服务器的所有从服务器中,挑选出一个作为新的主服务器

2.将其他从服务器的主服务器设置成新的

3.将已下线的主服务器的role改成从服务器,并将其主服务器设置成新的,当该服务器重新上线后,就会一个从服务器的角色继续工作

第一步中挑选新的主服务器的规则如下:

1.过滤掉所有已下线的从服务器

2.过滤掉最近5秒没有回复过Sentinel命令的从服务器

3.过滤掉与原主服务器断开时间超过down-after-milliseconds*10的从服务器

4.根据从服务器的优先级进行排序,选择优先级最高的那个

5.如果有多个从服务器优先级相同,则选取复制偏移量最大的那个

6.如果上一步的服务器还有多个,则选取id最小的那个

【编辑推荐】

  1. 大家所推崇的Redis分布式锁真的就万无一失吗?
  2. Java 框架之Redis 分布式缓存
  3. 基于内存和 Redis 的两级 Java 缓存框架
  4. 守护 Redis 安全的几个策略,你了解过几个呢?
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

16招轻松掌握PPT技巧

16招轻松掌握PPT技巧

GET职场加薪技能
共16章 | 晒书包

292人订阅学习

20个局域网建设改造案例

20个局域网建设改造案例

网络搭建技巧
共20章 | 捷哥CCIE

648人订阅学习

WOT2019全球人工智能技术峰会

WOT2019全球人工智能技术峰会

通用技术、应用领域、企业赋能三大章节,13大技术专场,60+国内外一线人工智能精英大咖站台,分享人工智能的平台工具、算法模型、语音视觉等技术主题,助力人工智能落地。
共50章 | WOT峰会

0人订阅学习

读 书 +更多

Java编程思想 第4版

本书共22章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、通过异常处理错误、字符串、泛型、数组、容器深入研究、Java I...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO播客