Redis哨兵-官方文档翻译

Posted by LB on Mon, Feb 24, 2020

Sentinel概述

Redis Sentinel为Redis提供高可用性。实际上,这意味着使用"哨兵"可以创建一个不需要人工干预就能抵抗某些类型失败的Redis部署。

Redis Sentinel还提供其他附属任务,如监控、通知和为客户提供配置。

这是宏观上(即全局)Sentinel功能的完整列表:

  • 监视:Sentinel会不断检查你的主实例和副本实例是否按预期工作。
  • 通知:Sentinel可以通过API通知系统管理员或其他计算机程序,其中一个被监控的Redis实例出了问题。
  • 自动故障转移:如果一个主服务器没有按照预期工作,Sentinel可以启动一个故障转移过程,其中一个副本被提升到主服务器,其他附加的副本被重新配置以使用新的主服务器,使用Redis服务器的应用程序在连接时被告知要使用的新地址
  • 组态设定提供者:Sentinel充当客户端服务发现的授权来源:客户端连接到Sentinels,以询问负责给定服务的当前Redis主服务器的地址。 如果发生故障转移,Sentinels将报告新地址。

Sentinel的分布式性质

Redis Sentinel是一个分布式系统:

哨兵本身被设计成在一个有多个协作的哨兵进程的配置中运行。有多个哨兵进程协作的好处如下:

  1. 当多个哨兵一致认为某个主节点不再可用时,就会执行故障检测。这降低了误报的概率。
  2. 即使不是所有的哨兵进程都在工作,哨兵也能工作,这使得系统对故障具有健壮性。毕竟,拥有一个本身就是单点故障的故障转移系统是毫无乐趣的。

哨兵、Redis实例(主实例和副本实例)和连接到哨兵和Redis的客户机的所有组成部分是一个更大的具有特定属性的分布式系统。在本文档中,将逐步介绍概念,从为了理解Sentinel的基本属性所需的基本信息,到为了理解哨兵的工作原理的更复杂的信息(可选)。

快速入门

获得哨兵

当前版本的Sentinel称为Sentinel 2。它是对最初的哨兵实现的重写,使用了更强大、更简单的预测算法(在本文档中有解释)。

自Redis 2.8起已发布稳定版本的Redis Sentinel。

在不稳定分支中进行了新的开发,并且有时新功能一旦被认为是稳定的,便会立即移植回最新的稳定分支。

Redis Sentinel版本1(随Redis 2.6一起发布)是不推荐使用的。

运行哨兵

如果您正在使用redis-sentinel可执行文件(或者如果您有一个与redis-server可执行文件同名的符号链接),您可以使用以下命令行运行Sentinel:

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

否则,您可以直接使用redis-server可执行文件以Sentinel模式启动它:

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

这两种方法的工作方式相同。

但是,在运行Sentinel时必须使用一个配置文件,因为系统会使用这个文件来保存在重新启动时要重新载入的当前状态。如果没有配置文件,或者配置文件路径不可写,Sentinel将拒绝启动。

哨兵默认情况下会监听TCP端口26379的连接,因此,为了使哨兵正常工作,必须打开服务器的端口26379,以接收来自其他哨兵实例的IP地址的连接。 否则,哨兵无法讨论也不能就该做什么达成共识,因此将永远不会执行故障转移。

部署哨兵前需要了解的基本内容

  1. 一个健壮的部署至少需要三个Sentinel实例。
  2. 应将三个哨兵实例放置到被认为以独立方式发生故障的计算机或虚拟机中。例如在不同的可用区域上执行的不同物理服务器或虚拟机。
  3. Sentinel + Redis分布式系统不保证在故障期间保留已确认的写入,因为Redis使用异步复制。但是,有一些部署Sentinel的方法使窗口丢失写入仅限于某些时刻,而还有其他一些不太安全的方法来部署它。
  4. 您的客户需要Sentinel支持。 流行的客户端库具有Sentinel支持,但不是全部。
  5. 如果您不经常在开发环境中进行测试,那么就没有HA设置是安全的,如果您可以在生产环境中进行测试,如果它们能够工作,那就更好了。你可能有一个错误的配置,只有当它变得太晚(凌晨3点当master停止工作)才会变得明显。
  6. Sentinel,Docker或其他形式的网络地址转换或端口映射应该小心混合:Docker执行端口重新映射,破坏了其他Sentinel进程的Sentinel自动发现以及主数据库的副本列表。有关更多信息,请参阅本文档后面有关Sentinel和Docker的部分。

配置哨兵

edis源发行版包含一个名为Sentinel .conf的文件,它是一个自文档化的示例配置文件,您可以使用它来配置Sentinel,但是典型的最小配置文件,如下所示:

1sentinel monitor mymaster 127.0.0.1 6379 2
2sentinel down-after-milliseconds mymaster 60000
3sentinel failover-timeout mymaster 180000
4sentinel parallel-syncs mymaster 1
5
6sentinel monitor resque 192.168.1.3 6380 4
7sentinel down-after-milliseconds resque 10000
8sentinel failover-timeout resque 180000
9sentinel parallel-syncs resque 5

您只需要指定要监视的主机,为每个单独的主机(可能有任意数量的副本)提供一个不同的名称。 无需指定自动发现的副本。 Sentinel将使用有关副本的其他信息自动更新配置(以便在重启时保留该信息)。 每当在故障转移期间将副本提升为主副本时,以及每次发现新的Sentinel时,都会重写配置。

上面的示例配置基本上监视两组Redis实例,每组实例由一个主实例和一个未定义数量的副本组成。一组实例称为mymaster,另一组称为resque。

哨兵监视器语句的参数含义如下:

1sentinel monitor <master-group-name> <ip> <port> <quorum>

为了清晰起见,让我们逐行检查配置选项的含义:

第一行用于告诉Redis监视一个名为mymaster的主机,该主机位于地址127.0.0.1和端口6379,仲裁者数量为2。一切都很明显,除了仲裁参数:

  • 仲裁人数是需要就主机不可到达这一事实达成共识的哨兵人数,以便将主机真正标记为发生故障,并在可能的情况下最终启动故障转移过程。
  • 然而,仲裁仅用于检测故障。为了实际执行故障转移,其中一个哨兵需要被选为故障转移的领导人,并被授权继续进行。这只会发生在哨兵进程的大多数投票中

例如,如果您有5个哨兵进程,并且给定主服务器的仲裁设置为2,则将发生以下情况:

  • 如果两个哨兵同时同意主节点不可到达,其中一个将尝试启动故障转移。
  • 如果至少有三个哨兵可用,则将授权故障转移并实际启动。

实际上,这意味着在故障期间,如果大多数标记进程无法通信(也就是在少数分区中没有故障转移),则标记进程将永远不会启动故障转移。

其他哨兵选项

其他选项几乎总是采用以下形式:

1sentinel <option_name> <master_name> <option_value>

及作下列用途:

  • down-after-milliseconds:是指Sentinel开始认为实例已关闭的情况下,该实例不应到达的时间(以毫秒为单位)(无论是不回复我们的PING还是出现错误)。
  • parallel-syncs:在故障转移后可以重新配置为使用新的主副本的副本数。该数字越小,完成故障转移过程所花费的时间就越多,但是,如果将副本配置为提供旧数据,则可能不希望所有副本同时与主数据库重新同步。虽然复制过程对副本来说基本上是非阻塞的,但有时它会停止从主服务器加载大量数据。您可能希望通过将此选项设置为值1来确保一次只能访问一个副本。

其他选项在本文的其余部分中进行了描述,并在Redis发行版附带的示例sentinel.conf文件中进行了说明。

所有配置参数都可以在运行时使用SENTINEL SET命令进行修改。有关更多信息,请参见Reconfiguring Sentinel at runtime章节。

哨兵部署示例

既然您已了解有关哨兵的基本信息,您可能会想知道应该将哨兵进程放置在何处,需要多少个哨兵进程等等。

本节展示一些示例部署。我们使用ASCII艺术,以图形格式向您展示配置示例:

1+--------------------+
2| This is a computer |
3| or VM that fails   |
4| independently. We  |
5| call it a "box"    |
6+--------------------+

我们在框内写下它们正在运行的内容:

1+-------------------+
2| Redis master M1   |
3| Redis Sentinel S1 |
4+-------------------+

不同的盒子用线连接起来,以表明它们能够通话:

1+-------------+               +-------------+
2| Sentinel S1 |---------------| Sentinel S2 |
3+-------------+               +-------------+

网络分区显示为使用斜线的中断线:

1+-------------+                +-------------+
2| Sentinel S1 |------ // ------| Sentinel S2 |
3+-------------+                +-------------+

还要注意:

  • 主节点称为M1,M2,M3,…,Mn。
  • 副本被称为R1, R2, R3,…, Rn (R代表replica)。
  • 哨兵被称为S1, S2, S3,…,Sn。
  • 客户被称为C1, C2, C3,…Cn。
  • 当实例由于哨兵动作而更改角色时,我们将其放在方括号中,因此[M1]表示由于哨兵干预而成为主实例的实例。
  • 请注意,我们永远不会显示仅使用两个哨兵的设置,因为哨兵始终需要与大多数人进行交谈才能启动故障转移。

示例1:仅两个哨兵,不要这样做

1+----+         +----+
2| M1 |---------| R1 |
3| S1 |         | S2 |
4+----+         +----+
5
6Configuration: quorum = 1
  • 在这个设置中,如果主M1失败,R1将被提升,因为两个哨兵可以就失败达成一致(显然将quorum设置为1),并且由于大多数是两个,因此也可以授权故障转移。所以很明显,表面上它可以工作,但是,请检查下面的要点,看看为什么这个设置是错误的。
  • 如果M1所在的盒子停止工作,S1也停止工作。在另一个机器S2中运行的标记将无法授权故障转移,因此系统将不可用。

请注意,需要多数才能订购不同的故障转移,然后将最新配置传播到所有Sentinel。 还要注意,在没有任何协议的情况下,在上述设置的单方面进行故障转移的能力将非常危险:

1+----+           +------+
2| M1 |----//-----| [M1] |
3| S1 |           | S2   |
4+----+           +------+

在上面的配置中,我们以完全对称的方式创建了两个主机(假设S2可以在没有授权的情况下进行故障转移)。客户可能会无限期地向双方写信,并且没有办法了解分区何时修复正确的配置,以防止出现永久性的脑裂状况

因此,请始终在三个不同的盒子中至少部署三个哨兵

示例2:三个盒子的基本设置

这是一个非常简单的设置,其优点是易于调整以提高安全性。它基于三个盒子,每个盒子运行一个Redis进程和一个标记进程。

 1       +----+
 2       | M1 |
 3       | S1 |
 4       +----+
 5          |
 6+----+    |    +----+
 7| R2 |----+----| R3 |
 8| S2 |         | S3 |
 9+----+         +----+
10
11Configuration: quorum = 2

如果主M1失败,则S2和S3将对失败达成一致,并将能够授权故障转移,从而使客户端能够继续。

在每个Sentinel设置中,由于Redis使用异步复制,因此始终存在丢失某些写入的风险,因为给定的已确认写入可能无法到达被提升为主副本的副本。在上述设置中,由于客户端被旧的主服务器分区,因此存在较高的风险,如下图所示:

 1         +----+
 2         | M1 |
 3         | S1 | <- C1 (writes will be lost)
 4         +----+
 5            |
 6            /
 7            /
 8+------+    |    +----+
 9| [M2] |----+----| R3 |
10| S2   |         | S3 |
11+------+         +----+

在这种情况下,网络分区隔离了旧的主数据库M1,因此副本R2被提升为主数据库。但是,与旧主服务器位于同一分区中的客户端(例如C1)可能会继续向旧主服务器写入数据。 此数据将永远丢失,因为当分区恢复正常时,主服务器将被重新配置为新主服务器的副本,从而丢弃其数据集。

使用以下Redis复制特性可以缓解此问题,该特性允许在主服务器检测到无法将写操作转移到指定数量的副本时停止接受写操作。

1min-replicas-to-write 1
2min-replicas-max-lag 10

使用上面的配置(请参阅Redis发行版中的自注释Redis .conf示例以获得更多信息),当Redis实例作为一个主实例时,如果它不能对至少一个副本进行写操作,则将停止接受写操作。由于复制是异步的,因此实际上无法写入意味着从副本已断开连接,或者未向我们发送异步确认超过指定的最大延迟秒数。

使用此配置,上面示例中的旧Redis master M1将在10秒后不可用。当分区恢复后,哨兵配置将收敛到新的配置,客户端C1将能够获取有效的配置并继续使用新的主服务器。

但是没有免费的午餐。 通过这种改进,如果两个副本都已关闭,则主服务器将停止接受写入。 这是一个权衡。

示例3:客户端盒子中的哨兵(特殊方案)

有时我们只有两个可用的Redis机器,一个用于主机器,另一个用于副本。在这种情况下,示例2中的配置是不可行的,因此我们可以采用以下方法,即在客户机所在的位置放置哨兵。

 1            +----+         +----+
 2            | M1 |----+----| R1 |
 3            |    |    |    |    |
 4            +----+    |    +----+
 5                      |
 6         +------------+------------+
 7         |            |            |
 8         |            |            |
 9      +----+        +----+      +----+
10      | C1 |        | C2 |      | C3 |
11      | S1 |        | S2 |      | S3 |
12      +----+        +----+      +----+
13
14      Configuration: quorum = 2

在此设置中,哨兵的观点与客户机相同:如果大多数客户机都可以访问主服务器,那就没问题。 C1,C2,C3是通用客户端,并不意味着C1标识连接到Redis的单个客户端。它更像是应用服务器、Rails应用程序或类似的东西。

如果运行M1和S1的机器发生故障,故障转移将不会出现问题,但是很容易看到不同的网络分区将导致不同的行为。例如,如果客户端和Redis服务器之间的网络断开,Sentinel将无法设置,因为Redis主服务器和副本都不可用。

请注意,如果C3被M1分区(在上述网络中几乎是不可能的,但是在不同的布局中或者由于软件层的故障,则更有可能),我们将遇到与示例2中所述类似的问题,区别在于 在这里,我们没有办法打破对称性,因为只有一个副本和一个主服务器,所以当主服务器与其副本断开连接时,主服务器无法停止接受查询,否则在副本失败时该主服务器将永远不可用。

因此,这是一个有效的设置,但是示例2中的设置具有以下优点,例如Redis的HA系统与Redis本身在相同的框中运行,可能更易于管理,以及在少数分区中设置主分区可以接收写操作的时间范围的能力。

示例4:少于三个客户端的Sentinel客户端

如果客户端少于三个框(例如三个Web服务器),则无法使用示例3中描述的设置。 在这种情况下,我们需要采用如下混合设置:

 1            +----+         +----+
 2            | M1 |----+----| R1 |
 3            | S1 |    |    | S2 |
 4            +----+    |    +----+
 5                      |
 6               +------+-----+
 7               |            |
 8               |            |
 9            +----+        +----+
10            | C1 |        | C2 |
11            | S3 |        | S4 |
12            +----+        +----+
13
14      Configuration: quorum = 3

这与示例3中的设置类似,但在这里,我们在四个可用的盒子中运行四个哨兵。如果主M1不可用,其他三个哨兵将执行故障转移。

从理论上讲,这种设置可以删除C2和S4运行的方框,并将quorum设置为2。然而,如果在我们的应用层中没有高可用性,我们就不太可能希望在Redis端使用HA。

哨兵,Docker,NAT和可能的问题

Docker使用了一种称为端口映射的技术:在Docker容器中运行的程序可能与它认为正在使用的端口不同。这对于在同一台服务器上同时运行多个使用相同端口的容器非常有用。

Docker并不是发生这种情况的唯一软件系统,还有其他网络地址转换设置,其中端口可以重新映射,有时不是端口,而是IP地址。

重新映射端口和地址会以两种方式导致Sentinel出现问题:

  1. 哨兵自动发现其他哨兵不再有效,因为它基于问候消息,其中每个哨兵宣布它们正在侦听连接的端口和IP地址。 但是,哨兵无法理解地址或端口是否已重新映射,因此它宣布的信息对于其他哨兵连接而言是不正确的。
  2. 副本以类似的方式列在Redis主服务器的INFO输出中:主服务器检查TCP连接的远程对等方时检测到该地址,而端口在握手期间由副本自身发布,但是该端口可能是 错误的原因与第1点所述相同。

由于哨兵使用主服务器INFO输出信息自动检测副本,因此检测到的副本将无法访问,并且哨兵将永远无法对主副本进行故障转移,因为从系统的角度来看,没有好的副本,因此目前没有用哨兵监视一组与Docker一起部署的主实例和副本实例,除非您指示Docker映射端口1:1。

对于第一个问题,如果您想使用带有转发端口的Docker(或重新映射端口的任何其他NAT设置)使用Docker运行一组Sentinel实例,则可以使用以下两个Sentinel配置指令来强制Sentinel宣布 特定的IP和端口集:

1sentinel announce-ip <ip>
2sentinel announce-port <port>

请注意,Docker可以在主机联网模式下运行(请检查–net=host选项以获取更多信息)。 这不会造成任何问题,因为在此设置中未重新映射端口。

快速教程

在本文档的下一部分中,将逐步介绍有关Sentinel API,配置和语义的所有详细信息。 但是,对于希望尽快使用系统的人来说,本节是一个教程,显示如何配置3个Sentinel实例并与之交互。

在这里,我们假设实例是在端口5000、5001、5002上执行的。我们还假设您在端口6379上具有正在运行的Redis主服务器,而副本服务器在端口6380上运行。 本教程,假设您正在个人计算机上运行模拟。

三个Sentinel配置文件应如下所示:

1port 5000
2sentinel monitor mymaster 127.0.0.1 6379 2
3sentinel down-after-milliseconds mymaster 5000
4sentinel failover-timeout mymaster 60000
5sentinel parallel-syncs mymaster 1

其他两个配置文件是相同的,但是使用5001和5002作为端口号。

关于上面的配置,有几点需要注意:

  • 这个主节点集合叫做mymaster。它标识主服务器及其副本。由于每个主集有不同的名称,所以哨兵可以同时监视不同的主集和副本集。
  • 仲裁设置为2(sentinel Monitor配置指令的最后一个参数)。
  • 毫秒后的下降值是5000毫秒,也就是5秒,所以一旦我们在这段时间内没有收到来自ping的任何回复,master将被检测为失败。

一旦你启动了三个哨兵,你会看到他们记录的一些日志信息,比如:

1+monitor master mymaster 127.0.0.1 6379 quorum 2

这是一个Sentinel事件,如果您订阅后面指定的事件名称,则可以通过Pub / Sub接收此类事件

在故障检测和故障转移期间,Sentinel生成并记录不同的事件。

向哨兵询问主机状态

在开始使用Sentinel时,最明显的做法是检查它所监视的主服务器是否运行良好:

 1$ redis-cli -p 5000
 2127.0.0.1:5000> sentinel master mymaster
 3 1) "name"
 4 2) "mymaster"
 5 3) "ip"
 6 4) "127.0.0.1"
 7 5) "port"
 8 6) "6379"
 9 7) "runid"
10 8) "953ae6a589449c13ddefaee3538d356d287f509b"
11 9) "flags"
1210) "master"
1311) "link-pending-commands"
1412) "0"
1513) "link-refcount"
1614) "1"
1715) "last-ping-sent"
1816) "0"
1917) "last-ok-ping-reply"
2018) "735"
2119) "last-ping-reply"
2220) "735"
2321) "down-after-milliseconds"
2422) "5000"
2523) "info-refresh"
2624) "126"
2725) "role-reported"
2826) "master"
2927) "role-reported-time"
3028) "532439"
3129) "config-epoch"
3230) "1"
3331) "num-slaves"
3432) "1"
3533) "num-other-sentinels"
3634) "2"
3735) "quorum"
3836) "2"
3937) "failover-timeout"
4038) "60000"
4139) "parallel-syncs"
4240) "1"

如您所见,它打印了大量关于master的信息。以下是我们特别感兴趣的一些:

  1. num-other-sentinels是2,因此我们知道Sentinel已经为该主服务器检测到了另外两个Sentinel。 如果您查看日志,将会看到生成的+ sentinel事件。
  2. flag显示为master。 如果主服务器宕机,我们也可以在这里看到s_down或o_down标志。
  3. num-slaves正确设置为1,因此Sentinel还检测到我们的主服务器有附加的副本。

为了进一步了解此实例,您可能需要尝试以下两个命令:

1SENTINEL slaves mymaster
2SENTINEL sentinels mymaster

第一个将提供有关连接到mater的副本的类似信息,第二个将提供有关其他Sentinel的信息。

获取当前主服务器的地址

正如我们已经指定的,Sentinel还充当想要连接到一组主服务器和副本的客户端的配置提供者。由于可能出现故障转移或重新配置,客户端不知道对于给定的一组实例,谁是当前活动的主人,因此Sentinel导出一个API来询问这个问题。

1127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
21) "127.0.0.1"
32) "6379"

测试故障转移

此时,我们的玩具哨兵部署已准备好进行测试。 我们可以杀死我们的主机,然后检查配置是否更改。 为此,我们可以这样做:

1redis-cli -p 6379 DEBUG sleep 30

此命令将使我们的主服务器停止响应,休眠30秒。它基本上模拟了由于某种原因挂起的主服务器。

如果查看哨兵日志,则应该可以看到很多操作:

  1. 哨兵检测主服务器的+sdown事件。
  2. 此事件随后被升级为+ odown,这意味着多个哨兵同意主节点不可访问的事实。
  3. 哨兵投票给将开始第一次故障转移尝试的哨兵。
  4. 故障转移发生。

如果您再次询问mymaster的当前主地址是什么,最终这次我们应该得到不同的答复:

1127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
21) "127.0.0.1"
32) "6380"

到目前为止一切顺利……此时,您可以跳转来创建哨兵部署,或者可以阅读更多内容以了解所有Sentinel命令和内部信息。

哨兵API

哨兵提供了一个API来检查其状态,检查被监控的主机和副本的健康状况,订阅以接收特定的通知,并在运行时更改Sentinel的配置。

默认情况下,哨兵使用TCP端口26379运行(请注意,6379是正常的Redis端口)。 哨兵使用Redis协议接受命令,因此您可以使用redis-cli或任何其他未修改的Redis客户端以便与哨兵进行通信。

可以直接查询哨兵,以从其角度检查受监视的Redis实例的状态,查看其知道的其他哨兵,等等。 或者,使用Pub / Sub,每次发生某些事件(例如故障转移或实例进入错误条件等)时,都可以从哨兵接收推式通知。

哨兵命令

以下是已接受命令的列表,但不包括用于修改Sentinel配置的命令,稍后将介绍这些命令。

  • PING 此命令仅返回PONG。
  • SENTINEL masters 显示被监视的master节点们及其状态的列表。
  • SENTINEL master < master name >:显示指定主机的状态和信息。
  • SENTINEL slaves < master name> :显示此主服务器的副本列表及其状态。
  • SENTINEL sentinels < master name>: 显示此主服务器的哨兵实例列表及其状态。
  • SENTINEL get-master-addr-by-name < master name>:返回具有该名称的主服务器的ip和端口号。 如果此主服务器正在进行故障转移或成功终止,它将返回升级副本的地址和端口。
  • SENTINEL reset < pattern >:此命令将重置所有具有匹配名称的主机。 pattern参数是glob样式的模式。 重置过程将清除主服务器中的所有先前状态(包括正在进行的故障转移),并删除已发现并与主服务器关联的每个副本和标记。
  • SENTINEL failover < master name>:强制进行故障转移,就好像主机无法访问一样,并且无需征得其他Sentinels的同意(但是将发布新版本的配置,以便其他Sentinels可以更新其配置)。
  • SENTINEL ckquorum < master name>:检查当前的Sentinel配置是否能够达到故障转移主节点所需的仲裁,以及授权故障转移所需的大多数仲裁。 在监视系统中应使用此命令来检查Sentinel部署是否正常。
  • SENTINEL ckquorum < master name>:强制Sentinel重写其在磁盘上的配置,包括当前的Sentinel状态。 通常,每当状态更改时(在重新启动后一直保留在磁盘上的状态子集的上下文中),Sentinel都会重写配置。 但是,有时由于操作错误,磁盘故障,程序包升级脚本或配置管理器,配置文件可能会丢失。 在这些情况下,强制Sentinel重写配置文件的方法很方便。 即使先前的配置文件完全丢失,此命令也有效。

在运行时重新配置哨兵

从Redis版本2.8.4开始,哨兵提供了一个API,以便添加,删除或更改给定主服务器的配置。 请注意,如果您有多个哨兵,则应将所有更改应用于您的实例,以使Redis 哨兵正常工作。 这意味着更改单个哨兵的配置不会自动将更改传播到网络中的其他哨兵。

以下是用于更新哨兵实例的配置的SENTINEL子命令的列表。

  • SENTINEL MONITOR < name> < ip> < port> < quorum>:此命令告诉哨兵开始监视具有指定名称,ip,端口和仲裁的新主服务器。 它与sendinel.conf配置文件中的哨兵监视器配置指令相同,不同之处在于您不能在ip中使用主机名,但需要提供IPv4或IPv6地址。
  • SENTINEL REMOVE < name>:用于删除指定的主机:主机将不再受到监视,并且将从Sentinel的内部状态中完全删除,因此SENTINEL主机将不再列出该主机,依此类推。
  • SENTINEL SET < name> < option> < value> :SET命令与Redis的CONFIG SET命令非常相似,用于更改特定主机的配置参数。可以指定多个选项/值对(或者根本不指定)。可以通过sentinel.conf配置的所有配置参数也可以使用SET命令进行配置。

以下是SENTINEL SET命令的示例,用于修改称为对象高速缓存的主机的毫秒级向下配置:

1SENTINEL SET objects-cache-master down-after-milliseconds 1000

如前所述,SENTINEL SET可用于设置启动配置文件中可设置的所有配置参数。 而且,可以更改主仲裁配置,而无需先删除并重新添加SENTINEL REMOVE和SENTINEL MONITOR,然后使用以下方法即可:

1SENTINEL SET objects-cache-master quorum 5

注意,这里没有等效的GET命令,因为SENTINEL MASTER以简单的解析格式(作为字段/值对数组)提供了所有配置参数。

增加或移除哨兵

由于哨兵实现了自动发现机制,因此向部署中添加新的哨兵是一个简单的过程。 您需要做的就是启动配置为监视当前活动主服务器的新哨兵。 在10秒钟内,哨兵将获取其他哨兵的列表以及附加到master的副本集。

如果需要一次添加多个Sentinels,建议先添加一个,再等待其他所有Sentinels已经知道第一个,然后再添加下一个。 为了仍然确保只能在分区的一侧实现多数,这很有用,因为在添加新的Sentinels的过程中可能会发生故障。

通过添加每个新的Sentinel(延迟30秒)以及在没有网络分区的情况下,可以轻松实现这一目标。

在该过程结束时,可以使用命令SENTINEL MASTER mastername来检查所有Sentinels是否都同意监视主服务器的Sentinels总数。

删除Sentinel有点复杂:哨兵永远不会忘记已经见过的哨兵,即使很长一段时间都无法访问它们,因为我们也不想动态更改授权故障转移和创建新配置号所需的多数。因此,要删除Sentinel,应在没有网络分区的情况下执行以下步骤:

  1. 停止要删除的哨兵的哨兵进程。
  2. 向所有其他Sentinel实例发送SENTINEL RESET 命令(如果您只想重置一个主机,则可以使用确切的主机名代替)。一个接一个,在两次实例之间至少等待30秒。
  3. 通过检查每个Sentinel的SENTINEL MASTER主机名的输出,检查所有Sentinels是否同意当前活动的Sentinels数量。

删除旧的主节点或无法访问的副本

哨兵永远不会忘记给定master的副本,即使长时间无法访问它们也是如此。 这很有用,因为在网络分区或故障事件之后,Sentinels应该能够正确地重新配置返回的副本。

此外,在故障转移之后,故障转移主服务器实际上被添加为新主服务器的一个副本,通过这种方式,它将被重新配置,以便在新主服务器再次可用时立即复制它。

然而,有时你想要永远从哨兵监视的副本列表中删除一个副本(可能是旧的master)。

为此,您需要向所有Sentinel发送SENTINEL RESET mastername命令:它们将在接下来的10秒钟内刷新副本列表,仅添加从当前主INFO输出中正确列出的副本。

发布/订阅消息

客户端可以使用Sentinel,因为它是与Redis兼容的Pub / Sub服务器(但您不能使用PUBLISH),以便订阅或订阅到频道并获得有关特定事件的通知。

通道名称与事件名称相同。 例如,名为+ sdown的通道将接收与进入SDOWN的实例相关的所有通知(从您要查询的Sentinel的角度来看,SDOWN意味着该实例不再可访问)。

要获取所有消息,只需使用PSUBSCRIBE *进行订阅。

以下是可使用此API接收的频道和消息格式的列表。 第一个单词是通道/事件名称,其余是数据格式。

注意:如果指定了实例详细信息,则意味着提供了以下参数来标识目标实例:

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

标识主服务器的部分(从@参数到末尾)是可选的,并且仅在实例本身不是主服务器时才指定。

  • +reset-master < instance details> – 主服务器被重置。
  • +slave < instance details> – 检测到一个新的副本并附加。
  • +failover-state-reconf-slaves < instance details> – 故障转移状态已更改为重新配置从属状态。
  • +failover-detected < instance details> – 检测到由另一个Sentinel或任何其他外部实体启动的故障转移(已将附加副本复制为主服务器)。
  • +slave-reconf-sent < instance details> – 为了重新配置这个副本,leader sentinel将SLAVEOF命令发送给这个实例。
  • +slave-reconf-inprog < instance details> – 正在重新配置的副本显示为新主ip:port对的副本,但同步过程尚未完成。
  • +slave-reconf-done < instance details> – 副本现在与新主服务器同步。
  • -dup-sentinel < instance details> – 指定的主机的一个或多个哨兵已被删除(例如,此操作在重新启动Sentinel实例时发生)。
  • +sentinel < instance details> – 一个新的哨兵为这个master被发现和连接。
  • +sdown < instance details> – 现在,指定的实例处于主观关闭状态。
  • -sdown < instance details> – 指定的实例不再处于主观关闭状态。
  • +odown < instance details> – 现在,指定的实例处于客观关闭状态。
  • -odown < instance details> – 指定的实例不再处于客观关闭状态。
  • +new-epoch < instance details> – 当前的纪元已更新。
  • +try-failover < instance details> – 新的故障转移正在进行中,等待由大多数人选出。
  • +elected-leader < instance details> – 赢得了指定时期的选举,可以进行故障转移。
  • +failover-state-select-slave < instance details> – 新的故障转移状态为select-slave:我们正在尝试寻找合适的副本进行升级。
  • no-good-slave < instance details> – 没有好的复制品可以推广。目前,我们将在一段时间后尝试,但是这种情况可能会改变,状态机将完全中止故障转移。
  • selected-slave < instance details> – 我们找到了要推广的指定好的副本。
  • failover-state-send-slaveof-noone < instance details> – 我们正在尝试将升级副本重新配置为主副本,等待它切换。
  • failover-end-for-timeout < instance details> – 故障切换因超时而终止,无论如何副本最终都将配置为与新的主副本一起复制。
  • failover-end < instance details> – 故障转移成功结束。所有副本似乎都被重新配置为使用新主服务器进行复制。
  • switch-master < master name> < oldip> < oldport> < newip> < newport> – 主新IP和地址是配置更改后指定的IP和地址。这是大多数外部用户感兴趣的消息
  • +tilt – 进入Tilt模式。
  • -tilt – 退出Tilt模式。

-BUSY状态的处理

当Lua脚本的运行时间超过配置的Lua脚本的时间限制时,Redis实例将返回-BUSY错误。在触发故障转移之前发生这种情况时,Redis Sentinel将尝试发送一个SCRIPT KILL命令,只有在脚本是只读的情况下才会成功。

如果该实例在尝试后仍处于错误状态,则最终将对其进行故障转移。

副本优先级 (Replicas priority)

Redis实例具有一个称为replica-priority(副本优先级)的配置参数。Redis副本实例在其INFO输出中公开了此信息,哨兵使用该信息以便从可用于故障转移master的副本中选择一个副本:

  1. 如果副本优先级设置为0,则永远不会将副本提升为master。
  2. 哨兵优先选择优先级较低的副本。

例如,如果当前主机的同一数据中心中有一个副本S1,而另一个数据中心中有另一个副本S2,则可以将S1的优先级设置为10,将S2的优先级设置为100,因此如果 主机失败,并且S1和S2均可用,S1将是首选。

有关选择副本方式的更多信息,请检查本文档的“副本选择和优先级”部分。

Sentinel和Redis身份验证

当将主服务器配置为要求客户端提供密码时,作为一种安全措施,副本也需要知道该密码,以便与主服务器进行身份验证并创建用于异步复制协议的主副本服务器连接。

使用以下配置指令可以实现此目的:

  • requirepass在主服务器中,以便设置身份验证密码,并确保实例不会处理未经身份验证的客户端的请求。
  • masterauth在副本中,以便让副本通过主服务器的身份验证,以便正确地从其中复制数据。

使用Sentinel时,没有单个主服务器,因为在故障转移之后,副本可能会充当主服务器,并且可以重新配置旧的主服务器以充当副本,因此您要做的是在 您的所有实例,包括主实例和副本实例。

这通常也是一种合理的设置,因为您不希望仅保护主服务器中的数据,而是希望在副本中访问相同的数据。

但是,在不常见的情况下,您需要一个无需身份验证即可访问的副本,您仍然可以通过将副本优先级设置为零,以防止将该副本提升为主副本,并仅在该副本中配置masterauth指令来做到这一点。 ,而无需使用requirepass指令,以便未经身份验证的客户端可以读取数据。

为了在使用requirepass配置哨兵时将哨兵连接到Redis服务器实例,Sentinel配置必须包括哨兵auth-pass指令,格式为:

1sentinel auth-pass <master-group-name> <pass>

使用身份验证配置Sentinel实例

您也可以配置Sentinel实例本身,以通过AUTH命令要求客户端身份验证,但是此功能仅从Redis 5.0.1开始可用。

为此,只需将以下配置指令添加到所有Sentinel实例中:

1requirepass "your_password_here"

以这种方式配置后,Sentinels将执行以下两项操作:

  1. 客户端需要密码才能发送命令到Sentinels。 这很明显,因为通常这是Redis中这种配置指令的工作方式。
  2. 此外,此Sentinel实例将使用配置为访问本地Sentinel的相同密码,以对其连接到的所有其他Sentinel实例进行身份验证。

这意味着您将必须在所有Sentinel实例中配置相同的requirepass密码。这样,每个Sentinel都可以与其他Sentinel进行对话,而无需为每个Sentinel配置访问所有其他Sentinels的密码,这是非常不切实际的。

在使用此配置之前,请确保您的客户端库能够将AUTH命令发送到Sentinel实例。

哨兵客户端实现

除非将系统配置为执行一个脚本,该脚本将所有请求透明地重定向到新主实例(虚拟IP或其他类似系统),否则Sentinel需要显式客户端支持。户端库实现的主题包含在文档Sentinel clients指南中。

更高级的概念

在接下来的小节中,我们将介绍一些有关Sentinel如何工作的细节,而不会涉及本文档最后一部分将介绍的实现细节和算法。

SDOWN和ODOWN故障状态

Redis Sentinel具有两个不同的关闭状态,一个称为主观关闭状态(SDOWN),它是给定Sentinel实例本地的关闭状态。另一种被称为客观下降条件(ODOWN),当足够多的哨兵(至少是被监控的主节点的仲裁参数配置的数量)具有一个SDOWN条件时,就会达到这个状态,并使用SENTINEL is-master- down -by-addr命令从其他哨兵那里获得反馈。

从Sentinel的角度来看,如果在配置中指定的秒数为is-master-down-after-milliseconds,则它没有收到对PING请求的有效答复,则达到SDOWN条件。

可以接受的对PING的回复如下所示:

  • PING回复了+ PONG。
  • PING回复-LOADING错误。
  • PING答复-MASTERDOWN错误。

任何其他答复(或根本没有答复)均被视为无效。 但是请注意,在INFO输出中将自己作为副本发布的逻辑主机被视为已关闭。

请注意,SDOWN要求在配置的整个时间间隔内没有接收到可接受的应答,因此,如果间隔为30000毫秒(30秒),并且我们每29秒接收到一个可接受的ping应答,则认为该实例正在工作。

SDOWN不足以触发故障转移:它仅表示单个Sentinel认为Redis实例不可用。 要触发故障转移,必须达到ODOWN状态。

要从SDOWN切换到ODOWN,无需使用强大的共识算法,而只是使用一种八卦的方式:如果给定的Sentinel收到报告,称主服务器在给定的时间范围内没有从足够的Sentinels工作,则将SDOWN提升为ODOWN。 如果此确认以后丢失,则清除标志。

为了真正启动故障转移,需要使用实际多数的更严格的授权,但是在未达到ODOWN状态之前无法触发任何故障转移。

ODOWN条件仅适用于master。 对于其他类型的实例,Sentinel不需要执行操作,因此副本和其他哨兵永远不会达到ODOWN状态,而只有SDOWN可以达到。

然而,SDOWN也有语义含义。例如,SDOWN状态下的副本不会被执行故障转移的标记提升。

哨兵和副本自动发现

哨兵与其他哨兵保持联系,以相互检查彼此的可用性,并交换信息。但是,您不需要在运行的每个哨点实例中配置其他哨点地址列表,因为哨点使用Redis实例的发布/订阅功能来发现监视相同主机和副本的其他哨点。

通过将问候消息发送到名为 __sentinel__:hello的通道来实现此功能。

同样,您无需配置附加到主数据库的副本列表,因为哨兵会通过查询Redis自动发现此列表。

  • 每个哨兵每两秒钟向每个受监视的主副本和副本Pub / Sub通道__sentinel__:hello发布一条消息,并通过ip,port,runid宣布其存在。
  • 每个哨兵都订阅了每个主副本和副本的pub / Sub通道__sentinel __:hello,以查找未知的标记。 当检测到新的标记时,会将它们添加为该主标记的标记。
  • Hello消息还包括主服务器的完整当前配置。 如果接收方哨兵的给定主控配置早于接收方的配置,它将立即更新为新配置。
  • 在将一个新的哨兵添加到一个主节点之前,哨兵总是检查是否已经有一个具有相同的runid或相同地址(ip和端口对)的岗哨。在这种情况下,所有匹配的哨兵都被移除,新的哨兵被添加。

在故障转移过程之外对实例进行哨兵重新配置

即使没有进行故障转移,Sentinels也会始终尝试在受监视实例上设置当前配置。 特别:

  • 声称是主服务器的副本(根据当前配置)将被配置为使用当前主服务器进行复制的副本。
  • 连接到错误主服务器的副本将被重新配置为使用正确的主服务器进行复制。

为了使Sentinels重新配置副本,必须在一段时间内观察到错误的配置,该时间大于用于广播新配置的时间。

这样可以防止配置过时的Sentinel(例如,因为它们刚从分区重新加入)将在接收更新之前尝试更改副本的配置。

  • 当故障转移的主机恢复可用时,它们将重新配置为副本。
  • 一旦到达分区,在分区期间分区的副本将重新配置。

关于这一部分要记住的重要教训是: Sentinel是一个系统,在该系统中,每个进程将始终尝试将最后的逻辑配置强加给受监视实例集。

复制节点选举和优先级

当Sentinel实例准备执行故障转移时,由于主服务器处于ODOWN状态,并且Sentinel从大多数已知的Sentinel实例获得了故障转移的授权,因此需要选择合适的副本。

副本选择过程计算下列关于副本的信息:

  1. Disconnection time from the master : 从主服务器断开连接的时间。
  2. Replica priority:副本优先级
  3. Replication offset processed:已处理的复制偏移量
  4. Run ID:运行ID

从哨兵进行故障转移的角度来看,发现副本与主服务器断开连接的时间超过已配置的主服务器超时的十倍(毫秒级选项),再加上主服务器不可用的时间, 被认为不适合故障转移,因此被跳过。

用更严格的术语来说,一个副本的INFO输出表明它已与主数据库断开连接的原因不止以下几点:

1(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

被认为是不可靠的,并且完全被忽略。

副本选择仅考虑通过上述测试的副本,并根据上述条件按照以下顺序对其进行排序。

  1. 副本按Redis实例的redis.conf文件中配置的副本优先级排序。 优先级较低的优先。
  2. 如果优先级相同,则检查副本处理的复制偏移量,并选择从主服务器接收更多数据的副本。
  3. 如果多个副本具有相同的优先级并处理了来自主服务器的相同数据,则会执行进一步的检查,选择字典顺序较小的运行ID的副本。 拥有较低的运行ID并不是副本的真正优势,但是对于使副本选择过程更具确定性很有用,而不是选择随机副本。

Redis master(可以在故障转移之后将其转换为副本)和副本都必须配置一个副本优先级(如果有机器是强首选的)。 否则,所有实例都可以使用默认的运行ID(建议的设置,因为它是通过复制偏移量选择副本的更有趣的方式)来运行。

一个Redis实例可以配置一个特殊的副本优先级为0,这样哨兵就永远不会选择它作为新的主进程。但是,哨兵仍然会重新配置以在故障转移后使用新主服务器进行复制,惟一的区别是它本身永远不会成为主服务器。

算法和内部

在以下各节中,我们将探讨哨兵行为的详细信息。 用户不一定非要知道所有详细信息,但深入了解哨兵可能有助于更有效地部署和操作哨兵。

仲裁数(Quorum)

前面几节说明了由Sentinel监视的每个主机都与一个已配置的仲裁相关联。它指定需要就主机的不可达性或错误情况达成一致的Sentinel进程数,以触发故障转移。

但是,在触发故障转移之后,为了实际执行故障转移,至少大多数岗哨必须授权岗哨进行故障转移。哨兵从不在只有少数哨兵存在的分区中执行故障转移。

让我们把事情讲清楚一点:

  • Quorum:为了将主进程标记为ODOWN,需要检测错误条件的标记进程的数量。
  • 故障转移由ODOWN状态触发。
  • 一旦故障转移被触发,尝试进行故障转移的哨兵将被要求请求对大多数哨兵的授权(如果将quorum设置为大于多数的数字,则需要请求对大多数哨兵的授权)。

差异看似微妙,但实际上很容易理解和使用。 例如,如果您有5个哨兵实例,并且仲裁数量设置为2,则一旦2个哨兵认为主服务器无法访问,就会触发故障转移,但是,两个哨兵中的一个只能在发生故障时进行故障转移至少获得3个哨兵的授权。

如果将仲裁配置为5,则所有哨兵必须就主错误情况达成一致,并且需要所有哨兵的授权才能进行故障转移。

这意味着可以通过两种方式使用仲裁数来调整哨兵:

  1. 如果将仲裁数设置为小于我们部署的大多数哨兵的值,那么我们基本上是在使哨兵对主服务器故障更加敏感,甚至在只有少数哨兵不再能够与主服务器对话时,也会触发故障转移。
  2. 如果将仲裁数设置为大于大多数哨兵的值,则只有在有大量(大于多数)连接良好的哨兵同意主服务器宕机时,我们才使哨兵能够进行故障转移。

配置纪元

由于一些重要的原因,哨兵需要获得大多数人的授权才能启动故障转移:

当一个哨兵被授权时,它会得到一个唯一的主节点的配置历期。该数字将在故障转移完成后用于对新配置进行版本控制。因为大多数人都同意将一个给定的版本分配给一个给定的哨兵,所以其他哨兵将不能使用它。这意味着每个故障转移的每个配置都使用唯一的版本进行版本控制。 我们将了解为什么这是如此重要。

此外,哨兵还有一个规则:如果一个哨兵投票给另一个哨兵,让他对指定的主人进行故障转移,那么他将等待一段时间再尝试对同一个主人进行故障转移。此延迟是您可以在sentinel.conf中配置的故障转移超时。这意味着哨兵不会在同一时间尝试对同一个master进行故障转移,第一个请求被授权的会尝试,如果失败了,另一个会在一段时间后尝试,以此类推。

Redis哨兵保证了它的活性,如果大多数哨兵都能说话,那么当master倒下时,最终会有一个被授权进行故障转移。

Redis岗哨还保证了安全性,即每个哨兵都将使用不同的配置时期对同一主服务器进行故障转移。

配置传播

一旦哨兵能够成功地对主站进行故障转移,它将开始广播新的配置,以便其他哨兵能够更新关于给定主站的信息。

为了使故障转移成功,它要求哨兵能够将SLAVEOF NO ONE命令发送到所选副本,并且稍后在主服务器的INFO输出中观察到切换到主服务器的情况。

此时,即使副本的重新配置正在进行中,故障转移也被认为是成功的,并且所有哨兵都必须开始报告新配置。

传播新配置的方式是我们需要使用不同版本号(配置纪元)授权每个标记故障转移的原因。

配置将在__sentinel__:hello Pub/Sub频道中广播

因为每个配置都有不同的版本号,所以较大的版本总是胜过较小的版本。例如,我的master的配置一开始所有的哨兵都认为master是192.168.1.50:6379。这个配置的版本是1。一段时间后,一个标记被授权使用版本2进行故障转移。如果故障转移成功,它将开始广播一个新配置,比如版本2的192.168.1.5:9000。所有其他实例将看到此配置并相应地更新其配置,因为新配置具有更大的版本。

这意味着哨兵保证了第二个活性属性:一组能够通信的哨兵都将收敛于具有更高版本号的相同配置。

基本上,如果对网络进行了分区,则每个分区都将收敛到更高的本地配置。 在没有分区的特殊情况下,只有一个分区,每个哨兵都会就配置达成一致。

分区下的一致性

Redis哨兵配置最终是一致的,因此每个分区都将收敛到可用的更高配置。 然而,在使用哨兵的真实系统中,有三种不同的玩家:

  • Redis instances : Redis实例
  • Sentinel instances :哨兵实例
  • Clients : 客户端

为了定义系统的行为,我们必须考虑这三个方面。

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

 1            +-------------+
 2            | Sentinel 1  |----- Client A
 3            | Redis 1 (M) |
 4            +-------------+
 5                    |
 6                    |
 7+-------------+     |          +------------+
 8| Sentinel 2  |-----+-- // ----| Sentinel 3 |----- Client B
 9| Redis 2 (S) |                | Redis 3 (M)|
10+-------------+                +------------+

在这个系统中,原始状态是Redis 3是主状态,而Redis 1和2是副本状态。旧主服务器之间发生了隔离。哨兵1和2启动了故障转移,提升哨兵1为新主人。

Sentinel属性可确保Sentinel 1和2现在具有主服务器的新配置。 但是,由于Sentinel 3位于不同的分区中,因此其配置仍旧。

我们知道,当网络分区修复后,Sentinel 3的配置将得到更新,但是,如果客户端被旧的主服务器分区,在分区期间会发生什么?

客户仍将能够写入旧版Redis 3。 当分区重新加入时,Redis 3将变成Redis 1的副本,并且分区期间写入的所有数据都将丢失。

根据您的配置,您可能希望或不希望发生这种情况:

  • 如果您使用Redis作为缓存,客户端B仍然能够向旧主服务器写入数据,即使它的数据将丢失,这可能会很方便。
  • 如果您使用Redis作为存储,这是不好的,您需要配置系统,以部分防止这个问题。

由于Redis是异步复制的,因此在此场景中无法完全防止数据丢失,但是可以使用以下Redis配置选项限制Redis 3和Redis 1之间的差异:

1min-replicas-to-write 1
2min-replicas-max-lag 10

使用上述配置(请参阅Redis发行版中的自我注释过的redis.conf示例以获取更多信息),Redis实例在充当主实例时,如果无法写入至少1个副本,将停止接受写入。 由于复制是异步的,因此实际上无法写入意味着复制副本已断开连接,或者未向我们发送异步确认超过指定的最大延迟秒数。

使用此配置,以上示例中的Redis 3将在10秒钟后不可用。 分区修复后,Sentinel 3配置将收敛到新配置,客户端B将能够获取有效配置并继续。

通常,Redis + Sentinel总体上是一个最终一致的系统,其中合并功能是最后的故障转移胜出,并且将丢弃来自旧主服务器的数据以复制当前主服务器的数据,因此总会有丢失确认写入的窗口 。 这是由于Redis异步复制以及系统“虚拟”合并功能的丢弃特性所致。 请注意,这不是Sentinel本身的限制,并且如果您使用高度一致的复制状态机来安排故障转移,则相同的属性仍将适用。 只有两种方法可以避免丢失已确认的写入:

  1. 使用同步复制(以及适当的共识算法来运行复制状态机)。
  2. 使用最终一致的系统,其中可以合并相同对象的不同版本。

Redis当前无法使用任何上述系统,并且目前不在开发目标之内。 但是,在Redis商店(如SoundCloud Roshi或Netflix Dynomite)之上有实现解决方案“ 2”的代理。

哨兵持久状态

哨点状态被保存在哨点配置文件中。例如,每次接收或创建一个新的主配置(leader Sentinels)时,该配置将与配置纪元一起保存在磁盘上。这意味着停止和重新启动标记进程是安全的。

TILT模式

Redis 哨兵在很大程度上取决于计算机时间:例如,为了了解实例是否可用,它会记住对PING命令最近一次成功回复的时间,并将其与当前时间进行比较以了解它的年代。

但是,如果计算机时间以意外的方式更改,或者计算机非常繁忙,或者由于某种原因导致进程阻塞,则哨兵可能会以意外的方式开始运行。

TILT模式是一种特殊的“保护”模式,当检测到某些异常现象时,哨兵可以进入该模式,这会降低系统的可靠性。 哨兵计时器中断通常每秒被调用10次,因此我们希望两次调用计时器中断之间大约会间隔100毫秒。

哨兵的作用是在上次调用计时器中断时进行注册,并将其与当前调用进行比较:如果时差为负或意外大(2秒或更长时间),则进入TILT模式(或者如果已经存在) 进入了从TILT模式退出的退出)。

在TILT模式下,哨兵将继续监视所有内容,但是:

  • 它完全停止了活动。
  • 由于不再信任检测故障的能力,因此它开始对SENTINEL is-master-by-addr请求作出否定答复。

如果30秒钟内一切正常,则退出TILT模式。

请注意,可以使用许多内核提供的单调时钟API以某种方式替换TILT模式。 但是,尚不清楚这是否是一个好的解决方案,因为当前系统避免了问题,以防进程只是被挂起或长时间未由调度程序执行。

原文链接:https://redis.io/topics/sentinel