上一篇介绍了Redis的主从服务器之间是如何同步数据的。试想下,在一主一从或一主多从的结构下,如果主服务器挂了,整个集群就不可用了,单点问题并没有解决。Redis使用Sentinel解决该问题,保障集群的高可用。

如何保障集群高可用

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

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

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

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

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

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

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

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

Sentinel

和上一小节的想法一样,Redis通过增加额外的Sentinel服务器来监控数据服务器,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即向该频道发布消息,又从该频道订阅消息。

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最小的那个

原文:Java架构笔记

免费Java高级资料需要自己领取,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G。             
传送门:             https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

分布式Redis深度历险-Sentinel的更多相关文章

  1. 分布式Redis深度历险-Cluster

    本文为分布式Redis深度历险系列的第三篇,主要内容为Redis的Cluster,也就是Redis集群功能. Redis集群是Redis官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来 ...

  2. 分布式Redis深度历险-复制

    Redis深度历险分为两个部分,单机Redis和分布式Redis. 本文为分布式Redis深度历险系列的第一篇,主要内容为Redis的复制功能. Redis的复制功能的作用和大多数分布式存储系统一样, ...

  3. Redis深度历险——核心原理与应用实践

    高可用架构」的各位老铁们,你们好!你是否还记得上个月发布的文章中,有两篇深入讲解Redis的文章,分别是和,广大粉丝读者们对这两篇文章整体评价颇高.而我就是这两篇文章的原创作者「老钱」(钱文品),我是 ...

  4. 《Redis深度历险:核心原理和应用实践》千帆竞发——分布式锁

  5. Redis深度历险,全面解析Redis14个核心知识点

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取. 传送门: ...

  6. 《Redis深度历险:核心原理和应用实践》学习笔记一

    1.redis五种数据结构 1.1 String字符串类型,对应java字符串类型 用户信息序列化后,可以用string类型存入redis中批量读写string类型,见效网络消耗数字类型的string ...

  7. 【Redis深度历险】那些年Redis的数据结构

    [Redis深度历险]那些年Redis的数据结构 Redis端口号6379的来源 Redis的端口号是6379,但这个端口号并不是随机选择的,源于"MERZ",这个单词在手机当中的 ...

  8. Redis 深度历险

    学习资料 https://juejin.im/book/5afc2e5f6fb9a07a9b362527 包括下面几方面的内容 基础 应用 原理 集群 拓展 源码 to be done

  9. redis深度历险:核心原理与应用实践--笔记

随机推荐

  1. CSS filter滤镜试玩

    1.模糊(blur). 用法:给相应元素设置高斯模糊,传入的px数值越大越模糊. 2.亮度(brightness). 用法:给元素设置亮度,0%为全黑,100%为元素原始亮度,>100%表示会比 ...

  2. docker环境无法执行jmap -heap 56命令

    很奇怪的问题,但是jstack可以执行 解决方法: docker 内部使用jmap 需要启动容器时候配置权限:docker run --privileged=true  --cap-add=SYS_P ...

  3. js个人笔记简记

    正则表达式 创建正则表达式的两种方法:   Var reg = new RegExp(‘’) Var reg = / a/ 后面三个参数g:全局匹配 i:不区分大小写 m:多行匹配 开头结尾有用 常见 ...

  4. AFNetworking遇到错误 Request failed: unacceptable content-type: text/html

    iOS 使用AFNetworking遇到错误 Request failed: unacceptable content-type: text/html 原因: 不可接受的内容类型 “text/html ...

  5. 【LeetCode】746. 使用最小花费爬楼梯

    使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始). 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或 ...

  6. windows双网卡绑定

     windows双网卡绑定                                            开门贱山:  以下内容纯属抄袭,如有雷同,也是醉了~~!! ————————————— ...

  7. STL关联容器的基本操作

    关联容器 map,set map map是一种关联式容器包含 键/值 key/value 相当于python中的字典不允许有重复的keymap 无重复,有序 Map是STL的一个关联容器,它提供一对一 ...

  8. 4. jenkins 构建任务

    这边说一下 ,服务器的分布.  因为我这边 测试环境的项目比较多,不能修改主机名 1号机器 节点机器(node) 最终项目发布到这台机器 2号机器  jenkins jenkins的部署,发布 3号机 ...

  9. Hive 读书札记

    把数据从一个关系型数据库直接导入 Hive,使用 Sqoop.

  10. python 画小猪佩奇

    转自:python画个小猪佩奇 # -*- coding: utf-8 -*- """ Created on Mon May 20 11:36:03 2019 @auth ...