您的位置:首页 > 数据库 > Redis

Redis --- Sentinel

2015-10-10 11:46 549 查看

Redis---Sentinel

下面内容翻译自网页:http://redis.io/topics/sentinel

RedisSentinel提供了Redis的高可用性方案。在实际中着意味着你可以通过使用Sentinel来创键一个Redis的方案来在不需要在认为干预的条件下防止某种类型的错误发生。

RedisSentinel也提供了一些附属的任务,比如监控,通知和作为客户端的一个配置提供者。

下面是从宏观角度看的Sentinel能力的一个完整列表

监控.Sentinel会常常检查主服务器和从服务器实例是否正常工作。
通知.Sentinel能在监控的redis实例出现问题时通过API来通过系统管理员,其他的计算机程序。
自动故障转移.如果主服务器出现异常,Sentinel可以启动一个故障转移进程,其中的一个从服务器会被推选为主服务器,其他的附加从服务器会重新配置实用新的主服务器,使用Redis的服务器会被通知新的用来连接的地址。
配置提供者.Sentinel可以作为向客户端服务发布服务的可信源。客户端连接到Sentinel来获取服务的当前的Redis主服务器的地址,如果发生故障转移,Sentinel会报告新的地址。

Sentinel的分布性本质

RedisSentinel是一个分布式系统:

Sentinel本身被设计在有多个Sentinel进程协同工作的环境中运行的。有多个Sentinel进程协同的优点如下:

当多个Sentinel都认为主服务器出现异常后才确认检测到错误,这样降低了检查错误的可能性。
Sentinel能在并不是所有的Sentinel进程都正常工作的时候工作,这样系统可能提高应对错误的强壮型。对于一个错误转移系统来说自己本身是一个单点失误毕竟不是一个有趣的事情。

总结一下:Redis实例(主服务器和从服务器)和客户端连接到Sentinel和Redis,这同样是一个有特定属性的分布式系统。本文档会逐步介绍这些概念,从一些了解Sentinel属性所需的基本知识开始,到为了更准确的理解Sentinel是如何工作的一些复杂的信息(这些是可选的)。

快速开始

获取Sentinel

Sentinel的当前版本是Sentinel2.这是对最初的Sentinel实现使用了更强大和简明的预测算法(文档中会进行说明)进行重写后的版本。

稳定的RedisSentinel版本是随同Redis2.8和3.0发布的,这是两个Redis的最新版本。

新的发布会在非稳定分支中,而新的特性当认为是稳定的时候有时会往前归入到2.8和3.0的版本中。

edisSentinel版本1,伴随的Redis2.6已经被丢弃,不应该再被使用。

运行Sentinel

如果你使用的是redis-sentinel的可执行文件(或者你有一个符号连接到一个redis-server的可执行文件上)你可以通过下面的命令来执行Sentinel:

redis-sentinel/path/to/sentinel.conf

另外你可以直接使用redis-server的可执行文件,以Sentinel的模式启动:

redis-server/path/to/sentinel.conf--sentinel

两种方式都是一样的。

不管怎么样,运行Sentinel都必须使用一个配置文件,这个配置文件会被系统使用来保存当前的状态以便重启的时候进行装载。Sentinel会在没有配置文件或配置文件不可写的时候拒绝启动。

Sentinels默认运行时监听TCP端口26379为了Sentinels可以工作,你的服务器的26739端口必须打开,并接受其它Sentinel实例的IP地址的连接,否则Sentinels之间无法对话,也无法统一该做什么,因此故障转移永远不会发生。

在部署Sentinel之前需要知道的事情

要进行一个强壮的部署至少要有3个Sentinel实例
这3个Sentinel实例必须部署认为失败是独立的计算机或虚拟机上。比如不同的物理服务器或不同的可用区域上运行的虚拟机。
Sentinel+Redis分布系统并不保证在故障发生时所承认的写会被保持,因为Redis使用异步复制,然而又一些方法可以部署Sentinel来使得损失写的窗口限制在一定的时期内,当然也有其它一些不太安全的部署方式
你需要Sentinel支持你的客户端,大部分客户端库支持Sentinel,但不是全部。
如果你没有时常的在部署环境,如果可以的话在生产环境更好,进行测试就不可能有高可用性的配置。当他们启动后,你可能有一些不合理的配置,当他们显现出来的时候就太晚了(比如凌晨3点,你的主服务器停止工作了)
Sentinel,Docker,或则其它形式的网络地址转换或端口映射应该小心处理:Docker执行端口映射,会破坏Sentinel自动发现其他的Sentinel进程和主服务器的其它从服务器。可以通过查看Docker和Sentinel相关的章节来了解更多的信息。

配置Sentinel

Redis源码发布中包含一个称为sentinel1.con的配置文件,这是一个自我说明的示例配置文件,你可以用它来配置Sentinel,然而,一个典型的最小的配置文件看起来就像下面这样:

sentinelmonitormymaster127.0.0.163792

sentineldown-after-millisecondsmymaster60000

sentinelfailover-timeoutmymaster180000

sentinelparallel-syncsmymaster1


sentinelmonitorresque192.168.1.363804

sentineldown-after-millisecondsresque10000

sentinelfailover-timeoutresque180000

sentinelparallel-syncsresque5

你只需指定要监控的主服务器,每一个单独的主服务器需要一个单独的名字(可能有多个从服务器)。不需要配置从服务器,从服务器是自动发现的。Sentinel1会自动更新配置文件,添加关于从服务器的信息(为了在重启的情况下维持这些信息)。配置同样会在每次某个从服务器在故障转移时被推举为主服务器和每一次一个新的Sentinel被发现时被更新。

上面配置的例子,配置了监控Redis实例的两个集合,每一个包含一个主服务器和一个未确定数量的从服务器,一个实例集合称为mymaster,另一个为resque.

Sentinelmoniter声明参数的含义如下:

sentinelmonitor<master-group-name><ip><port><quorum>

为了更加清楚,我们逐行来解释这些选项的含义:

第一行用来告诉Redis去监控一个主服务器称为mymaster,地址是127.0.0.1,端口是6379,法定人数为2,每一个参数都很清楚了,除了这个quorum参数:

Quorum是Sentinels的数量,这是需要对主服务器不可用的情况,为了更切确的标注从服务器故障和甚至是否需要启动一个故障转移的这些情况达成一致的Sentinel的数量
然而quorum只用来检测失败,为了在实际中执行一个故障转移,其中的一个Sentinels需要被推举为首领并被收取来进行。这只会发生在多数的Sentinel进程的之间投票。

举个例子,加入有5个Sentinel进程,而对一个主服务器集合给定的quorum是2,则会如下:

如果两个Sentinels同时认为主服务器已经不可用了,其中的一个会启动故障转移。
如果之手有3个Sentinels是可用的,故障转移会被授权并实际发生。

在实际的情况中这意味着在故障期间如果大多数的Sentinel进程无法相互通信,Sentinel是不会启动一个故障转移的(故障转移不会发生在小部分区间)。

其它的Sentinel选项

其他的选项格式如下:

sentinel<option_name><master_name><option_value>

目的如下:

down-after-milliseconds
设置了当超过指定的毫秒时间后一个实例没有响应PINGS或返回错误的情况下Sentinel会认为这是不可用的。

parallel-syncs
设置了在故障转移之后会同时被重新配置到新的主服务器上的从服务器的数量,数字越低,故障转移完成花费的时间就越长,然而如果从服务器被配置来使用了就的数据,你可能不想所有的从服务器都同时和主服务器进行重同步。虽然复制进程一般来说是不会阻塞从服务器的,但又一个时间段会停下来装载从主服务器中获取的快数据,你可能想确保只有一个从服务器是一个时间段是不可用的,可以通过设置该选项为1.


其它的选项在本文档的其它地方和随Redis发布的示例配置文件sentinel.conf1中会进行描述。

所有的配置参数在运行是都是可以改变的,并且通过SENTINELSET命令可以促使其生效。可以参看—运行时重新配置Sentinel–章节来获取更多信息。

Sentinel部署示例

在你已经知道了关于Sentinel的基本信息,你可以想知道该在什么地方部署Sentinel进程,需要部署多少个Sentinel进程等等,本章节会显示一些部署示例

我们使用ASCII艺术来以图形的格式来展示例子,这里有一些不同含义的符号:

+--------------------+

|Thisisacomputer|

|orVMthatfails|

|independently.We|

|callita"box"|

+--------------------+

会在箱子中描述运行的哪些东西:

+-------------------+

|RedismasterM1|

|RedisSentinelS1|

+-------------------+

不同的箱子之间用连线表明他们是可以对话的:

+-------------++-------------+

|SentinelS1|---------------|SentinelS2|

+-------------++-------------+

网络的隔开会是用斜线隔开的线条表示。

+-------------++-------------+

|SentinelS1|------//------|SentinelS2|

+-------------++-------------+

还有一些注意的地方:

主服务器会称呼为M1,M2,M3,…,Mn.
从服务器会称为R1,R2,R3,…,Rn(R表示复制)
Sentinel会称为S1,S2,S3,…,Sn.
客户端称为C1,C2,C3,…,Cn
当一个实例因为Sentinel的行为改变角色是,我们会将器放在一对方括号内,所以[M1]标识一个实例因为Sentinel的干预现在称为一个主服务器了

注意,不会展示只有两台Sentinels被使用时的场景,因为Sentinels总是需要在多数Sentinel间对话来启动故障转移。

Example1:只有两个Sentinel,不要这样做

+----++----+

|M1|---------|R1|

|S1||S2|

+----++----+


配置:quorum=1


在这个配置中个,如果主服务器M1失败了,R1会被推举为主服务器,因为两个Sentinels可以就失败达成一致(因为quorum设置成1),所以表面上是可以工作的,然而检查下下面的情况来看下为什么这种配置是失败的。
如果M1所在的箱子停止了工作,那S1也停止了工作,而运行在其他箱子中的S2会无法被授权来进行故障转移,因此系统会不可用。

注意到大多数是需要用来安排不同的故障转移后后续的最新配置文件传递到所有的Ssentinel的,也要注意到在这个配置如果中一个节点中可以进行故障转移,而不需要任何达成的一致,会是非常危险的。

+----++------+

|M1|----//-----|[M1]|

|S1||S2|

+----++------+

在上面的配置中我们产生了两个主服务器(假定S2可以未经授权进行故障转移),以完全对称的方式。客户端可能向两边都写入了无限的数据,而当隔离恢复的时候就无法确定那边的配置是正确的了,这就是要防止产生的永久隔离大脑情况。

所以请在不同的箱子中部署至少3个Sentinel.

Example2:3个箱子的基本配置

着是一个非常简单的配置,这有可以简单的调整来增加安全性的优点,基于3个箱子,每一个箱子运行一个Redis进程和一个Sentinel进程。

+----+

|M1|

|S1|

+----+

|

+----+|+----+

|R2|----+----|R3|

|S2||S3|

+----++----+


配置:quorum=2

如果主服务器M1失败,S2和S2会认同失败,并可以授权失败转移,使得客户端可以继续连接。

在每一个Sentinel设置中,因为Redis是异步复制的,因此总是存在损失一些写操作的危险,因为认可的写可能还没有达到会被推举为主服务器的从服务器。然而在上面的配置对于客户端来说有一个更改的风险是由于旧的主服务器被隔离开了,向下面图片显示的一样。

+----+

|M1|

|S1|<-C1(writeswillbelost)

+----+

|

/

/

+------+|+----+

|[M2]|----+----|R3|

|S2||S3|

+------++----+

在这个例子中,一个网络中断隔离了旧的主服务器M1,因此R2被推举为主服务器,然而客户端,比如C1,和就的主服务器在同一个网络区间,可能会继续往旧的主服务器写数据,这些数据在隔离恢复的时候会永久的丢失,因为旧的主服务器会被重新配置为新主服务器的从服务器,而忽略自己的数据集合。

这个问题可以通过使用以下的Redis复制特点来缓和,这允许当主服务器监测到无法传输写到指定数量的从服务器时拒绝写操作。

min-slaves-to-write1

min-slaves-max-lag10

当使用上面的配置时(请查看在Redis发布中的自注释的redis.conf例子获取更多信息)一个Redis实例,当作为一个主服务器时会在其无法向至少一个从服务器写时停止接受写操作。因为复制是异步的,无法写就意味着从服务器要么是无法连接,要么是无法在最大的max-lag数量的秒数内返回异步的相应。

使用这个配置,上面例子中旧的Redis主服务器M1会在10秒变为不可用。当隔离恢复时,Sentinel配置会变成一个心底,客户端C1可以获取一个合法的配置,并继续连接到新的主服务器。

没有免费的午餐,在这个精确的控制下,如果两个从服务器都宕机,那主服务器将拒绝接收写,这就是交换。

Example3:Sentinel部署在客户端箱子中

有时候我们只有两个Redis箱子可用,一个用来作为主,一个作为从,那例子2种的配置就无法使用了,我们可以采用下面的手段,Sentinel被安置到客户端。

+----++----+

|M1|----+----|R1|

|S1|||S2|

+----+|+----+

|

+------------+------------+

|||

|||

+----++----++----+

|C1||C2||C3|

|S1||S2||S3|

+----++----++----+


配置:quorum=2

在这个配置中,Sentinels的视角和客户端是一样的:如果一个主服务器是大多数的客户端可以连接的,那就是好的。C1,C2,C3是普通的客户端,这不意味着C1只是一个连接到Redis的单一客户端,它通常是类似应用服务器,Redis应用或其他的。

如果M1和S1所在的箱子失败了,故障转移会毫无疑问的发生,然而看懂啊不同的网络隔离会造成不同的行为,比如Sentinel会在客户端和Redis服务无法连接的时候无法配置,因为Redis的主服务器和从服务器都已经不可用了。

注意到如果C3和M1被隔离了(对于上面的网络情况来说是几乎是不可能的,但是更可能会由于不同的层次造成的,或则由于软件层的失败),就和例子2种的情况有些类似了,不同的是我们没有办法破坏对称,因为只有一个主服务器和从服务器,因此只有要么主服务器继续接收请求或者是由于从服务器的故障而永远不可用。

因此这是一个可用的配置,但是例子2更有优点,因为Redis的高可用系统和Redis本省运行在同样的箱子中,这样便于管理,也可以限制当主服务器称为少数隔离是可以接收写的时间间隔。

Example4:Sentinel在客户端,并少于3个客户端

例子三描述的情况在当没有3个客户端的情况下无法使用(比如3个web服务器),在这个情况下我们需要采用像下面的混合配置:

+----++----+

|M1|----+----|R1|

|S1|||S2|

+----+|+----+

|

+------+-----+

||

||

+----++----+

|C1||C2|

|S3||S4|

+----++----+


配置:quorum=3

这很像例子3,但是我们在可用的4个箱子中运行了4个Sentinel,如果M1不可用,其它的3个Sentinels会执行故障转移。

理论上这个配置在C2和S4所在的箱子移除时,将quorum设置成2也可以工作。然而这时不可行的,因为我们期望Redis的高可用性保持在Redis端,而不是依赖于应用层。

Sentinel,Docker,NAT和可能的问题。

Docker使用端口映射的技术:运行在Docker容器内的程序可能会暴露为一个和程序认为在使用的端口不通的端口。这样在多个容器同时使用同一服务器的同一端口的情况下是有用的。

Docker不是这种功能的唯一如软件,有一些其它的网络地址转换工具不仅可以映射端口,连IP地址都可以映射。

映射端口和地址会对Sentinel以下面两种形式产生问题:

Sentinel对其它Sentinel的自动发现功能无法工作了,因为这是基于每一个Sentinel在监听的端口和地址上的Hello信息来工作的,然而Sentinel没有办法理解一个映射过的端口或IP地址,因此它声明的信息是无法被其他Sentinels用来正确连接的。
从服务器在Redis主机端的INFO列表中以类似的方式保存着:地址是由简称TCP连接的远端,而端口是由从服务器在握手的时候宣称的,然而和第一点一样,这个端口可能是不正确的了。

因为Sentinels使用Maseters的INFO输出信息来监测从服务器,监测到的从服务器将是无法到达的,Sentinel也就永远无法进行故障转移了,这是因为从系统的角度当前没有一个正常的从服务器,也就没有方法在部署Docker的情况下去使用Sentinel来监控这个主服务器和从服务器实例的集合了,出发你制定Docker端口是1:1映射的。

因为存在上面的问题,在你想要使用Docker来指向端口(或者其他的进行端口映射的工具)的情况下来使用Sentinel实例,你可以使用下面的Sentinel配置指令来迫使Sentinel来声明一个IP和端口集:

sentinelannounce-ip<ip>

sentinelannounce-port<port>

注意到Docker有能力运行在hostnetworkingmode下(检查–net=host配置项)。在这个配下不会造成任何问题,因为端口不会被重映射。

快速指导

在文档的下个章节,所有关于SentinelAPI,配置和语义的细节都会被逐渐的覆盖到,对于尽快想要使用系统的人,本章是一个显示如何快速配置和使用3个Sentinel实例的指导。

这里假定实例使用端口5000,5001,5002。我们同样假定在6379上运行Redismaster,而salve运行在6380上。使用IPV4回送地址127.0.0.1,假定你在你的个人电脑上运行模拟器。

3个Sentinel配置文件应该看起来是这样子的:

port5000

sentinelmonitormymaster127.0.0.163792

sentineldown-after-millisecondsmymaster5000

sentinelfailover-timeoutmymaster60000

sentinelparallel-syncsmymaster1

其它的两个配置文件中使用5001,5002来作为端口。

关于上面的配置有一些需要说明:

主集称为mymaster.这确定了主服务器和从服务器,因为每一个主集有不同的名字,Sentinel可以同时监控不同的主服务器和从服务器集合。
法定人数设置成2(sentinel监控配置指令的最后一个参数)
Down-after-millseconds值设置为5000毫秒,也就是5秒,因此如果我们的pings在5秒后没有收到主服务器的响应则检测为失败。

你启动了3个Sentinel,你会看到日记中的一些信息,比如:

+monitormastermymaster127.0.0.16379quorum2

这是一个Sentinel时间,后面你如果设置了订阅的事件名称,你可以通过Pub/Subb接收到事件。

Sentinel会在失败检测和故障转移过程中生成和记录不同的事件。

向Sentinal查询主服务器的状态

Sentinel开始使用最常见的一件事情是检查监控的主服务器的状态:

$redis-cli-p5000

127.0.0.1:5000>sentinelmastermymaster

1)"name"

2)"mymaster"

3)"ip"

4)"127.0.0.1"

5)"port"

6)"6379"

7)"runid"

8)"953ae6a589449c13ddefaee3538d356d287f509b"

9)"flags"

10)"master"

11)"link-pending-commands"

12)"0"

13)"link-refcount"

14)"1"

15)"last-ping-sent"

16)"0"

17)"last-ok-ping-reply"

18)"735"

19)"last-ping-reply"

20)"735"

21)"down-after-milliseconds"

22)"5000"

23)"info-refresh"

24)"126"

25)"role-reported"

26)"master"

27)"role-reported-time"

28)"532439"

29)"config-epoch"

30)"1"

31)"num-slaves"

32)"1"

33)"num-other-sentinels"

34)"2"

35)"quorum"

36)"2"

37)"failover-timeout"

38)"60000"

39)"parallel-syncs"

40)"1"

可以看到,这里打印了关于主服务器的一些信息。有一些是我们感兴趣的:

Num-other-sentinels是2,所以我们知道Sentinel已经监测到了这个主服务器的其它两个Sentinel,如果你检查日记,可以看到+sentinel事件生成了。
Flags是master,如果master宕机了,我们会期望看到一个s_down或o_down的状态。
Num-slaves设置为1,也就是Sentinel也监测到了主服务器的从服务器。

为了显示实例的更多信息,你可以使用下面的两个命令:

SENTINELslavesmymaster

SENTINELsentinelsmymaster

第一个命令会提供连接到主服务器的从服务器的类似信息,第二个是关于其它Sentinel的。

获取当前主服务器的地址

前面提到过,Sentinel也可以作为一个想连接到主服务器和从服务器集的客户端的配置提供者。因为可能发生故障转移或重新配置,客户端并不知道当前活跃的实例集中主服务器,所有Sentinel提供一个API来实现这个功能:

127.0.0.1:5000>SENTINELget-master-addr-by-namemymaster

1)"127.0.0.1"

2)"6379"

测试故障转移

到目前为止,我们的Sentinel部署已经可以进行测试了,我们杀死主服务器,然后检查下配置是否改变,只需要:

redis-cli-p6379DEBUGsleep30

这个命令会使得我们的主服务无法连接,休眠30秒,这基本上可以模拟了由于某些原因造成的主服务器失败状态。

果你检查Sentinel日记,你会发现一些事情:

没一个Sentinel检测到主服务器的宕机,产生一个+sdown时间。
这个事件随后升级为+odown,表示多个Sentinel对主服务器无法连接的事实达成一致。
Sentinel投票出一台Sentinel,该Sentinel会启动故障转移。
故障转移进行

如果你在重新查询mymaster当前主服务器的地址,最终我们会获得一个和之前不同的响应:

127.0.0.1:5000>SENTINELget-master-addr-by-namemymaster

1)"127.0.0.1"

2)"6380"

到目前一切都正常,你可以能想去创建自己的Sentinel部署,或者了解关于Sentinel命令和内部的更多内容了。

SentinelAPI

Sentinel提供了检查自身状态,检查监控的主服务器和从服务器的状态,订阅来接收特定通知和运行时改变Sentinel配置的API。

默认情况下,Sentinel使用TCP端口26379(6379一般是Redis端口),Sentinels使用Redis协议来接收命令,所以可以使用redis-cli或其他未修改的Redis客户端来和Sentinel进行回话。

直接向Sentinel查询从其角度看来监控的Redis服务器状态是可能的,来查看其所知道的其它的Sentinel等。另外可以使用Pub/Sub,来从Sentinels接收Push类型的通知,没当时间发生,比如故障转移或某个实例进入了错误的状态等。

Sentinel命令

Thefollowingisalistofacceptedcommands,notcoveringcommandsusedinordertomodifytheSentinelconfiguration,whicharecoveredlater.

下面是Sentinel接受的命令列表,并不包括用来修改Sentinel配置的命令,其它的会在后面涉及到。

PING这个命令简单返回PONG
SENTINELmasters显示监控的主服务器的列表和它们的状态
SENTINELmaster
<mastername>
显示指定的主服务器的状态
SENTINELslaves
<mastername>
显示指定的主服务器的从服务器列表和状态
SENTINELsentinels
<mastername>
显示指定的主服务器对应的Sentinel列表和状态
SENTINELget-master-addr-by-name
<mastername>
返回指定名字的主服务器的IP和端口,如果正在发生故障转移或该主服务器正常关闭了,则返回推选的从服务器的地址和IP。
SENTINELreset
<pattern>
本命令重置所有复合模式的主服务器,模式参数是一个glob-style模式,重置进程清楚主服务器的任何前期状态(包括正在发生的故障转移),移除所有发现的相关的从服务器和Sentinel
SENTINELfailover
<mastername>
当主服务器无法连接时,没有询问其他Sentinels而强制执行一个故障转移,(这样后,一个新版本的配置文件会被发布,其它的Sentinel会更新配置文件)
SENTINELckquorum
<mastername>
检查当前的Sentinel配置是否可以达到需要进行故障转移的和转移授权的法定数量,本命令应该用来监控系统,检查Sentinel部署是否正常。
SENTINELflushconfig迫使Setinel重写其配置文件到硬盘上,包括当前的Sentinel状态。通常来说Sentinel会在每次状态发生变化时重写其配置文件(原先状态是重启是固话在硬盘上的状态)。然而又可能会由于操作失误,硬盘故障,包更新脚本或配置管理的原因造成配置文件丢失。在这种情况下迫使Sentinel重写配置文件的方法就是需要的。本命令就工作在如果之前的配置文件完全丢失的情况下。

运行时重新配置Sentinnel

Redis2.8.4版本开始,Sentinel提供了一个API来对一个指定主服务器的配置进行增加,删除和修改。注意到如果你有多个Sentinel,你应该将这些改变作用到你所有的RedisSentinel实例。这意味着修改单个Sentinel的配置不会自动将改变传递到网络上的其它Sentinel上。

下面是Sentinl的一些修改Sentinel实例配置的命令列表

SENTINELMONITOR
<name>
<ip>
<port>
<quorum>
该命令告诉Sentinel开始监控一个新的主服务器,有指定的名字,IP,端口和法定数量。它和Sentinel配置文件中的monitor指令是一样的,区别是这里不能使用主机名来作为IP,需要提供一个ipv4或ipv6的地址。
SENTINELREMOVE
<name>
用来移除指定的主服务器,该主服务器不会再被监控,会完全从Sentinel的内部状态中移除,因此也不会再出现在Sentinel的主服务器列表中。
SENTINELSET
<name>

<option>
<value>
SET命令和Redis的CONFIGSET命令很像,用来改变指定主服务器的配置参数,可以指定多个option/value对。所有可以在Sentinel.conf中配置的参数都可以使用SET命令进行设置。

下面是一个使用SET命令来改变名为object-cache-master的主服务器的down-after-milliseconds配置的例子:

SENTINELSETobjects-cache-masterdown-after-milliseconds1000

前面提到,SENTINELSET可以用来设置启动配置文件中可用的所有参数,另外也可以用来指示改变主服务器的法定数量配置,而不用移除或重新添加主服务器(使用SENTINELMONITOR和SENTINELREMOVE),值需要简单使用:

SENTINELSETobjects-cache-masterquorum5

注意没有更SET对应的GET命令,因为SENTINELMASTER以一种易于解析的格式提供了所有的配置参数(像一个field/value对数组)

增加和移除Sentinels

对你的部署添加一个新的进程是非常简单,因为Sentinel实现了自动发现的机制。你需要做的所有事情就是启动一个Sentinel并配置成监控当前活跃的主服务器,在10秒钟之内Sentinel会获取到其它Sentinel的列表和对应主服务器的从服务器集合。

如果你需要通知增加多个Sentinel,建议是一个个的添加,等到其它Sentinel都已经发现第一个后再增加下一个。这是为了保证大多数是会划分到一个区间里面的,这样再增加的过程中故障转移也能正常进行。

这可以简单的通过再网络畅通的情况下每隔30秒的延迟添加一个新的Sentinel来实现。

最后可以通过使用SENTINELMASTERmastername命令来检查是否所欲的Sentinel都对监控的主服务器的Sentinel数量保持一致。

移除一个Sentinel就有一点复杂了:Sentinel永远不会忘记一个已经存在的Sentinel。即使是已经是很长世间都无法连接的。这是因为我们不想动态的改变需要用来授权一个故障转移和新配置创建的数量。为了移除一个Sentinel,需要在网络畅通的情况下进行下面的步骤:

停止想要移除的Sentinel的进程
给每一个Sentinel实例发送一个SENTINELRESET*命令(如果只是针对一个主服务器,可以使用主服务器名来替换*)。一个接着一个来,中间间隔30秒。
检查所有的Sentinel是否对当前活跃Sentinel的数量保持一致,通过查看每一个Sentinel的SENTINELMASTERmastername命令的输出即可。

移除旧的主服务器或不可用的从服务器。

Sentinel不会忘记给定的主服务器的从服务器,即使是已经长时间无法连接了。这在发生网络隔断或故障转移是能够正确的重新配置一个重新可用的从服务器时是有用的。

另外,在故障转移之后,发生故障的主服务器会虚拟的添加有新主服务器的一个从服务器,也会再可用的时候从新配置成新主服务器的一个复制。

然而有时候需要Sentinel的从服务器列表中永久的移除一个从服务器(这也可能是旧的主服务器)

为了实现这个目的,你需要像所有的Sentinel发送SENTINELRESETmasetername命令,他们会再10秒内更新从服务器的列表,仅仅增加当前主服务器INFO输出中存在的从服务器。

Pub/Sub消息

客户端可以使用Sentinel来左右一个和Reids兼容的发布/订阅服务器(但是不能使用PUBLISH)来SUBSCRIBE或PSUBSCRIBE到通道上来获取特定的事件。

通道名和时间名是一样的。比如名字未+sdown的通道会在关联的实例进行一个SDOWN情况是接收到通知(SDOWN意味着该实例从你查询的Sentinel的角度来看是不可连接的)

可以通过使用PSUBSCRIBE*来获取所有的信息。

下面是使用该API可以获取的通道列表和消息格式。第一个词是通道或事件的名称,剩下的是数据的格式。

注意:instancedetails是指使用以下参数来确定的一个目标实例。

<instance-type><name><ip><port>@<master-name><master-ip><master-port>

定义主服务器的部分(从@参数开始到结束)是可选的,只有在指定的实例不是主服务器时才需要。

+reset-master
<instancedetails>
--主服务器重启.
+slave
<instancedetails>
--一个新的从服务器被发现并绑定.
+failover-state-reconf-slaves
<instancedetails>
--Failover状态改变为
reconf-slaves
状态.
+failover-detected
<instancedetails>
--由另一个Sentinel启动了故障转移或其它外部的实体被监测到(一个绑定的从服务器转变为主服务器)。
+slave-reconf-sent
<instancedetails>
--首领SENTINEL发送了SLAVEOF命令到该实例来重新配置新的从服务器。
+slave-reconf-inprog
<instancedetails>
--从服务器被配置为一个新的主服务器(ip:port)的从服务器,但是同步的进程还没有完成
+slave-reconf-done
<instancedetails>
--从服务器和新的主服务器完成了同步
-dup-sentinel
<instancedetails>
--一个或多个Sentinel针对主服务器被认为是重复的而被移除(这发生在Sentinel实例进行重启时)
+sentinel
<instancedetails>
--检测到主服务器的一个新的Sentinel和绑定。
+sdown
<instancedetails>
--指定实例处于SubjectivelyDown状态。
-sdown
<instancedetails>
--指定实例不在处于SubjectivelyDown状态。
+odown
<instancedetails>
--指定实例处于ObjectivelyDown状态.
-odown
<instancedetails>
--指定实例不再处于ObjectivelyDown状态。
+new-epoch
<instancedetails>
--当前epoch被更新了.
+try-failover
<instancedetails>
--新的故障转移在进行中,等待被多数选定。
+elected-leader
<instancedetails>
--赢得特定epoch的选举,可以进行故障转移
+failover-state-select-slave
<instancedetails>
--新的故障转移状态:select-slave:正在尝试找到一个合适的从服务器来提升。
no-good-slave
<instancedetails>
--没有合适的从服务器来进行提示,会在一段时间后重试,但是可能会发生变化,状态机可能会完全放弃这次的故障转移。
selected-slave
<instancedetails>
--找到了一个适合提升的从服务器。
failover-state-send-slaveof-noone
<instancedetails>
--正在尝试重新配置被提升的从服务器为主服务器,等待其进行转换。
failover-end-for-timeout
<instancedetails>
--故障转移由于超时而中断,从服务器最终会被配置为其它的新的主服务器的复制。
failover-end
<instancedetails>
--故障转移成功完成,所有的从服务器会被重新配置为新的主服务器的的复制。
switch-master
<mastername><oldip><oldport><newip><newport>
--主服务器在配置改变会会更新新的IP和端口,这个信息通常是外部用户会感兴趣
+tilt–进入Tilt模式.
-tilt–退出Tilt模式.

Handlingof-BUSYstate

当Lua脚本运行的时间超过了配置的Lua脚本运行时间限制Redis会返回-BUSY状态。当这种情况发生在触发故障转移之前,Sentiel会重试发送SCRIPTKILL命令,只有在脚本是只读的情况下该命令才会成功。

如果实例再执行了这个尝试之后仍然处于错误状态,它最终会被故障转移掉。

从服务器优先级

Redis实例有一个称为slave-priority的配置参数,该信息会被Redis从服务器在其INFO输出中显示。Sentinel使用改内容来在进行故障转移时挑选从服务器:

如果优先级为0,该从服服务器永远不会被推选为主服务器。
优先级数字越低的从服务器会被Sentinel优先选择

比如有一个从服务器S1和当前的主服务器处于同一个数据中心,另一个从服务器S2在另外一个数据中心,就可能设置S1的优先级为10,S2优先级为100,这样当主服务器发生故障时,如果S1和S2都是可用的,那S1会被优先选择。

关于从服务器被选择的方法的更多信息,可以查看从服务器选择和优先级章节。

Sentinel和Redis鉴定

当主服务器配置为需要客户端提供密码时,也就是一种安全的方法,从服务器在创建用于复制的主-从连接时需要提供这个密码以便主服务器可以认定

可以通过下面的配置指令来实现:

在主服务器中设置requirepass来设置认证的密码,确保实例不会处理来自为认证的客户端的请求。
在从服务器中配置masterauth来向主服务器进行认证,确保正确的复制数据。

当Sentinel使用时,没有一个单一的主服务器,因为在故障转移之后从服务器可能扮演主服务器的角色,而旧的主服务器可以被重新配置为从服务器。因此需要做的就是在所有实例中都配置上面的两条指令,包括主服务器和从服务器。

这也是一种合理的设置,因为你不仅是只想保护在主服务器中的数据,在从服务器中也保持同样的数据获取限制。

然而在一些不常用的情况下,你想要提供一个从服务器来进行未授权的访问,你可以通过设置该从服务器的优先级为0来实现,这样就保证该从服务器不会被推选为主服务器,只需要在这个从服务器中配置masterauth指令,不需要配置requirepass指令,这样就可以使用未授权的客户端来获取数据了。

Sentinel客户端实现

Sentinelrequiresexplicitclientsupport,unlessthesystemisconfiguredtoexecuteascriptthatperformsatransparentredirectionofalltherequeststothenewmasterinstance(virtualIPorothersimilarsystems).Thetopicofclientlibrariesimplementation
iscoveredinthedocument
Sentinelclientsguidelines.

Sentinel需要客户端直接的支持,除非系统配置了一个脚本来透明的将所有请求重新发送到新的主服务器实例(虚拟IP或其它类似的系统)。关于客户端库实现的主题在Sentinel客户端指导中会涉及。

更多高级概念

下面章节中我们会覆盖Sentinel如何工作的部分内容,具体的实现细节和算法会在本文档的最后部分涉及。

SDOWNandODOWN失败状态

RedisSentinel有两个宕机的不同概念,一个是SubjectivelyDown,这是某一个给定的Sentinel实例判断的状态,另一个为ObjectivelyDown,这是当足够多的Sentinel(至少是监控的主服务器配置的法定数量)都出现了SDOWN条件,并且通过SENTINELis-master-down-by-addr命令得到了其它Sentinel的反馈。

从Sentinel的角度来看,SDOWN情况是当没有在配置中由is-master-down-after-milliseconds配置的秒数内从主服务器收到PING请求的合法响应。

PING的合法响应包括:

PINGrepliedwith+PONG.
PINGrepliedwith-LOADINGerror.
PINGrepliedwith-MASTERDOWNerror.

任何其它的响应(或者没有响应)都认为是不合法的。注意,如果以逻辑上的主服务器在其INFO中宣称自己是从服务器,则认为其宕机了。

注意SDOWN是指在配置的指定秒数内没有合法响应,所以比如内部配置了30000毫秒(30秒),而我们在29秒时收到PING的响应,认为该实例是正常工作的。

SDOWN状态不足以出发一个故障转移:它只意味这一个单个的Sentinel认为Redis实例已经不可用了,要触发故障转移,必须达到ODOWN状态。

从SDOWN转换到ODOWN,并没有使用到强一致的算法,只是一种散播的方式:如果一个给定的Sentinel在给定的时间范围内收到足够多的Sentinel报告说主服务器已经宕机了,则SDOWN改变为ODOWN。如果响应丢失了,则清楚该标志。

更加严格的授权会使用要求的大多数来真正启动故障转移,但是没有故障转移可以在未到达ODWON状态之前触发。

ODWON状态只作用于主服务器,对于其他类型的实例,Sentinel不要求去执行,从服务器和其它的SENTINELS永远不会达到ODOWN状态,只会出现SDOWN状态。

然而SDOWN也有语义暗示,比如一个从服务器属于SDOWN状态则在故障转移时不会被推选为主服务器。

Sentinel和从服务器的自动发现

Sentinel会保持和其它Sentinel的连接,这样就可以相互的检查各自的可用性和交换信息。然而你不需要在每一个Sentinel实例中配置一个其它Sentinel的地址,因为Sentinel使用Redis实例的发布/订阅能力来自动发现监控同一个主服务器的其它的Sentinel和从服务器。

这个功能是通过向名字为
__sentinel__:hello的通道发送hello信息来实现的。


类似的,你不需要配置主服务器相关的从服务器的列表,因为Sentinel会自动发现这个Redis列表。

每一个Sentinel会向其监控的所有主服务器和从服务器的发布/订阅通道
__sentinel__:hello
每两秒发送一个信息,来声明它的存在,包括IP,PORT,runid.

每一个Sentinel对订阅每一台主服务器和从服务器的
__sentinel__:hello
通道来发现未知的sentinel.当新的sentinel被监测到,他们会被添加到这个主服务器的Sentinel列表来。

Hello消息也包括主服务器的当前配置,如果接收消息的Sentinel有比接收到的当前主服务器的配置旧的配置,则会立即更新这个配置。
在将一个Sentinel增加到主服务器之前,Sentinel总是会检查是不是有一个同样的runid或同样地址(ip和port),已经存在。这样的话,旧的Sentinel会被移除,然后新的加入进来。

非故障转移情况下实例的Sentinel重配置

Specifically:即使是没有发生故障转移,Sentinel也会尝试去配置监控实例的当前配置,特别是:

声明为主服务器的从服务器会被配置为当前主服务器的从服务器。
连接到错误主服务器的从服务器会被重新配置为正确的主服务器的复制。

为了Sentinel可以重新配置从服务器,错误的配置必须在某些时刻被发现,这会大于用来广播新配置的时间。

这样会阻止一个有失效配置的Sentinel会去在接收到更新之前去改变从服务器的配置。

另外要注意到总是尝试使用最新的配置是如何保证故障转移对于分区来说更加可靠:

当失效的主服务器在重新可用后会被配置为从服务器。
被隔断的从服务器恢复后会被重新配置。

关于本章要记住的重要一点是:Sentinel是一个每个进程都会尝试应用最新的配置到监控的实例的系统。

从服务器选举和优先级

当Sentinel实例准备执行一个故障转移时,(主服务器处于ODOWN状态,Sentinel收到大多数Sentinel实例的授权来进行故障转移),一个合适的从服务器会被选中。

从服务器选择进程评估从服务器的下列信息:

和主服务器失联的时间.
从服务器优先级.
处理的复制偏移
RunID.

一个从服务器发现和主服务器失去连接超过了配置的主服务器(down-after-milliseconds选项)的十倍,再加上从Sentinel进行故障转移的角度来看主服务器也是不可用了,会被认为是不适合进行故障转移而被跳过。

用更严密的话来说就是一个从服务器的INFO输出中显示已经和主服务器失联超过:

会被认为是不可靠的,而完全不被考虑。

从服务器选举制考虑通过了上面的检查的,并按照上面的标准按照下面的顺序进行排序:

从服务器按照redis.conf中定义的slave-priority进行排序,越低的越优先。
如果优先级是一样的,则检查处理的复制偏移,从主服务器获取到数据越多的被选中。
如果多个从服务器有同样的优先级和同样的处理的来自主服务器的数据,将进行接下来的检查,则按字典顺序来比较runID.更小的runID对从服务器来说并不是一个真正的优点,但相比于随机选择一个从服务器来说对使得从服务器选举进程更加的确定是有用的。

Redis主服务器(可能在故障转移之后会被转换为从服务器),和从服务器都强烈建议配置一个从服务器优先级。否则所有的实例可能都会使用默认的runID(这是建议的设置,因为比起按照复制偏移来选择从服务器来说更加的有趣)

一个Redis实例可以配置特殊的slave-priority:0,这样该实例就永远不会被Senitnel在故障转移时选择为新的主服务器,区别就是这个使用永远不会成为主服务器。

算法和内部原理

下面章节我们会解释下Sentinel行为的细节,对于用户来说了解所有的细节不是必须的,但是对Sentinel的深入了解可能对更有效的部署和操作Sentinel会有帮助。

Quorum法定数量

之前的章节中提到,由Sentinel监控的主服务器都会配置一个quorum.这指定了需要对主服务器不可用或错误达成一致并出发故障转移的Sentinel的进程数量。

然而,当故障转移出发后,为了让故障转移真正发生,至少要有大部分的Sentinels授权某个Sentinel进行故障转移,隔离在小部分区间的Sentinel永远不会执行故障转移。

让我们描述的更清晰一点:

Quorum:需要监测到主服务器的错误状态的Sentinel进程数量,然后才能将主服务器标志设置为ODOWN。
ODOWN会出发故障转移
故障转移出发后,尝试进行故障转移的Sentinel会向大部分的Sentinel(如果quorum设置的数字比大部分大,可能会超过大部分)要求授权。

这个区别可能看起来很微妙,但很好理解。比如如果有5个Sentinel实例,quorum设置为2,当2个Sentinel认为主服务器不可用了就会出发Sentinel,这两个Sentinel中的一个只有在获取到至少3个Sentinel的授权之后才可以进行故障转移。

如果quorum设置为5,则所有的Sentinel都必须认同主服务器处于错误状态,所有的Sentinel都必须授权才可以进行故障转移。

这意味着quorum可以用来以下面两种方式来调整Sentinel

如果quorum设定的值小于大部署的Sentinel的大部分值(超过一半),可以使得Sentinel对主服务器的故障更加敏感,会尽可能会的触发故障转移,因为只需要小部分的Sentinel无法和主服务器进行会话就可以认定了。
如果quorum设置的值超过了Sentinel的大部分值,Sentinel使得故障转移只发生在非常多的Sentinel认为主服务器不可用的时候。

配置epochs

Sentinel要求得到大部分的授权才启动故障转移是由于一下一些重要的原因:

当一个Sentinel被授权以后,会获得进行故障转移的主服务器的一个唯一的配置纪元,这个一个用来在故障转移完成后标识配置新版本的数字。因为大部分都同意了这个版本是指派为某一个Sentinel,而其它的Sentinel就不能使用了,这意味着每一次故障转移的每一个配置都会是一个唯一的版本。我们会看到为什么这很重要。

另外Sentinel有一个规则:如果一个Sentinel选择了其它的Sentinel来对一个主服务器进行故障转移,它会等待一些时间,然后去尝试对同样的主服务器进行故障转移,这个延迟就是sentinel.conf中配置的failover-timeout.这意味着Sentinel不会同时对同一个主服务器进行故障转移,第一个获取授权的会先尝试,如果失败了,另一个会在一定时间后再尝试,照此下去。

RedisSentinel保证一个活跃属性:当大部分Sentinel可以相互会话时最终其中的一个在主服务器宕机后会被授权来进行故障转移。

RedisSentinel同样保证一个安全属性:每一个Sentinel会使用不同的配置纪元来对同一个主服务器进行故障转移。

配置传播

当一个Sentinel能够承购的完成主服务器的故障转移,它会对新的配置进行广播,这样其它的Sentinel会更新他们关于主服务器的信息。

要使得故障转移认为是成功的,需要Sentinel发送SLAVEOFNOONE命令到选中的从服务器,然后可以从INFO输出中观察到该从服务器转换为了主服务器。

在这个时刻,即使从服务器的重配置还在进行中,故障转移也认为已经成功了,然后所有的Sentinel需要开始记录新的配置。

新配置传播的方式也是我们需要每一个Sentinel的故障转移由一个不同的版本数字来认证的原因(配置纪元)

每一个Sentinel使用Redis的发布/订阅持续的广播其主服务器的配置版本,不进在主服务器,也在所有的从服务器进行。同时Sentinel也等待信息来查看其它的Sentinel宣称的配置。

配置在
__sentinel__:hello发布/订阅通道上广播。


因为每一个配置有一个不同的版本信息,所有更大的版本总是会替换所有小的版本。

因此比如mymaster配置开始时所有的Sentinel都认为主服务器是192.168.1.50:6379。配置版本为1,一段时间后,一个Sentinel被授权来进行故障转移,版本为2,当故障转移成功后,它会广播一个新的配置,假定是192.168.1.50:9000,版本2。所有的其它实例会看到这个配置,并会相应的更新他们的配置,就是因为新的配置有一个更高的版本。

这标识Sentinel保证了第二个活跃属性:一个Sentinel集合如果可以相互通讯会集中使用同一个更高版本的配置。

基本上如果网络是隔离的,而每一个隔断会聚合到一个高的本地配置,在没有隔断的特定情况下,所有的Sentinel会对配置达成一致。

隔离情况下的一致性

RedisSentinel配置最终是一致的,一次每一个隔离会聚集到一个可用的较高的配置。然而在使用Sentinel的真实环境中,有3个不同的角色:

Redisinstances.
Sentinelinstances.
Clients.

为了定义系统的行为,我们必须考虑到所有。

下面是一个有3个节点的简单网络,每一个节点运行一个Redis实例和一个Sentinel实例:

+-------------+

|Sentinel1|-----ClientA

|Redis1(M)|

+-------------+

|

|

+-------------+|+------------+

|Sentinel2|-----+--//----|Sentinel3|-----ClientB

|Redis2(S)||Redis3(M)|

+-------------++------------+

在这个系统中,原始状态是Redis3是主服务器,Redis1,2是从服务器。一个隔断发生后隔离了旧的主服务器,Sentinel1,2会启动一个故障转移,假定推选了Redis1做为新的主服务器。

Sentinel的属性保证了Sentinel1和2现在有关于主服务器的同样配置,然而Sentinel3依然保留着旧的配置,因为它被隔离在不同的区间里。

我们知道Sentinel3会在网络隔断恢复后更新配置,然而如果有客户端和旧的主服务器隔断在同一个区间会发生什么呢?

客户端会依然可以写Redis3(旧的主服务器),当区间重新连接后,Redis会被调整为Redis1的从服务器,所有在隔离期间写入的数据将丢失。

依据你的配置,你可能期望或不期望发生这样的事情:

如果你使用Redis作为缓存,客户端B依然可以写旧服务器是方便的,即使数据最终会丢失。
如果你使用Redis作为存储,那就不合适了,你需要重新配置系统来尽量的防止这个问题。

因为Redis是异步复制的,是没有办法完全保证这个场景中的数据丢失,然而你可以在Redis3和Redis1中限制这种分歧,使用以下配置:

min-slaves-to-write1

min-slaves-max-lag10

有了上面的配置(可以查看在Redis发布版本中自解释的redis.conf实例获取更多的信息),一个Redis实例当作为主服务器是,如果不能实际写向至少一个从服务器时会拒绝接收写请求,因为复制是异步的,不能实际写指的是或者是从服务器失去了连接,或则是在超过了指定max-lag的描述后没有收到异步的响应。

使用这个配置后,上面例子中的Redis3会在10秒后不可用,当隔断恢复后,Sentinel配置会更新到新的版本,客户端B可以获取一个合法的配置然后继续使用。

IngeneralRedis+Sentinelasawholeareaaneventuallyconsistentsystemwherethemergefunctionis
lastfailoverwins,andthedatafromoldmastersarediscardedtoreplicatethedataofthecurrentmaster,sothereisalwaysawindowforlosingacknowledgedwrites.ThisisduetoRedisasynchronousreplicationandthediscardingnatureof
the"virtual"mergefunctionofthesystem.NotethatthisisnotalimitationofSentinelitself,andifyouorchestratethefailoverwithastronglyconsistentreplicatedstatemachine,thesamepropertieswillstillapply.Thereareonlytwowaystoavoidlosing
acknowledgedwrites:

总的来说Redis+Sentinel作为一个整体最终是一个始终保持一致的系统,整合的方法就是最后的故障转移会胜出。旧的主服务器的数据会被忽略,然后从新的主服务器复制数据,因此总是有一个窗口会丢失已认可的写,这是由Redis的异步复制来决定的和系统的虚拟融合功能的本质决定的。注意到这不是Sentinel本事的一个限制,如果你使用一个强一致的复制状态机器来进行故障转移,依然会出现同样的特点。只有两种方法可以保证不丢失认可的写:

使用同步复制(和一个适合的共识算法来运行一个复制的状态机)
一个最终一致的系统来保证不同版本的对象可以进行融合。

Redis当前不能使用上述的任何一个系统,当前也是在部署的目标之外的。然而在Redis存储之上有一些替代的实现方案2比如SoundCoudRoshi或者NetflixDynomite.

Sentinel固话状态

Sentinel状态会被固话在Sentinel的配置文件中,比如每一次收到关于主服务器的一个新的配置或者创建新的(首领Sentinel,负责故障转移),配置会和配置纪元一起固话到硬盘中,这意味着停止和重启Sentinel进程是安全的。

TILTmode

RedisSentinel是严重依赖于计算机时间的:对于实例来说确认一个实例是否可用就是记录上次PING的正确响应时间,然后和当前时间进行比较来确认的。

然而如果计算机时间异常改变了,或则是计算机繁忙,或则是由于某些原因进程堵塞了Sentinel可能会出现一些异常的行为。

TheTILTmodeisaspecial"protection"modethataSentinelcanenterwhensomethingoddisdetectedthatcanlowerthereliabilityofthesystem.TheSentineltimerinterruptisnormallycalled10timespersecond,soweexpectthatmoreorless100milliseconds
willelapsebetweentwocallstothetimerinterrupt.

TILT模式是一种特殊的保护模式,这样一个Sentinel可以在一些奇怪的事情发生时进入状态来降低系统的可用性。Sentinel时钟中断通常来说会每一秒调用10次,因此我们可以明确在两次时钟中断之间有差不多100毫秒。

WhataSentineldoesistoregistertheprevioustimethetimerinterruptwascalled,andcompareitwiththecurrentcall:ifthetimedifferenceisnegativeorunexpectedlybig(2secondsormore)theTILTmodeisentered(orifitwasalreadyenteredthe
exitfromtheTILTmodepostponed).

Sentinel所做的就是记录上次调用时钟中断的时间,然后和当次调用比较,如果时间间隔是负的或则异常的大(2秒或更多)TILT模式就会启动(或者是已经进入TILT模式推迟的状态)

当Sentinel处于TILT模式时,会继续监控所有的事情,但是:

完全停止执行
开始否定的响应SENTINELis-master-down-by-addr请求来使得可以被检测到不可信的失败状态

如果事情恢复正常超过30秒,TILT模式会退出。

注意,某种程度上TILT模式可以使用很多内核提供的monotonicclockapi来代替。然而因为当前系统会回避进程只是挂起或长时间没有被执行器执行的情况,索引还不能确定这是一个好的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: