Redis Sentinel 的高可用性

非集群 Redis 的高可用性

Redis 堆栈 Redis 社区版

Redis Sentinel 在不使用 Redis Cluster 时为 Redis 提供高可用性。

Redis Sentinel 还提供其他附带任务,例如监控、 通知,并充当客户端的配置提供程序。

以下是 Sentinel 在宏观层面(即大局)功能的完整列表:

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

Sentinel 作为分布式系统

Redis Sentinel 是一个分布式系统:

Sentinel 本身设计为在多个 Sentinel 进程协同工作的配置中运行。多个 Sentinel 进程协作的优势如下:

  1. 当多个 Sentinel 就给定主控不再可用这一事实达成一致时,将执行故障检测。这降低了误报的可能性。
  2. 即使并非所有 Sentinel 进程都正常工作,Sentinel 也能正常工作,从而使系统能够抵御故障。毕竟,拥有一个本身就是单点故障的故障转移系统并没有什么乐趣。

Sentinels、Redis 实例(主实例和副本实例)和客户端的总和 连接到 Sentinel 和 Redis 也是一个更大的分布式系统,具有 特定属性。在本文档中,将逐步介绍概念 从了解基本所需的基本信息开始 属性,以 以了解 Sentinel 的工作原理。

Sentinel 快速入门

获取 Sentinel

Sentinel 的当前版本称为 Sentinel 2。它是 使用更强、更简单的 Sentinel 初始实现 算法(本文档中对此进行了说明)。

Redis Sentinel 的稳定版本从 Redis 2.8 开始提供。

unstable 分支中执行新的开发,以及新功能 有时,一旦它们被移植到最新的稳定分支中 被认为是稳定的。

Redis 2.6 附带的 Redis Sentinel 版本 1 已弃用,不应使用。

运行 Sentinel

如果您使用的是redis-sentinel可执行文件(或者如果您有 链接到redis-server可执行文件),您可以运行 Sentinel 使用以下命令行:

redis-sentinel /path/to/sentinel.conf

否则,您可以直接使用redis-serverexecutable 启动它 哨兵模式:

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

两种方式的工作原理相同。

但是在运行 Sentinel 时必须使用配置文件,因为系统将使用此文件来保存当前状态,该状态将在重新启动时重新加载。如果未提供配置文件或配置文件路径不可写,Sentinel 将拒绝启动。

默认情况下,Sentinel 会运行侦听到 TCP 端口 26379 的连接,因此 要使 Sentinel 正常工作,必须打开服务器的端口 26379 才能接收 来自其他 Sentinel 实例的 IP 地址的连接。 否则,Sentinels 无法交谈,也无法就该怎么做达成一致,因此故障转移 永远不会执行。

部署 Sentinel 之前需要了解的基本知识

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

配置 Sentinel

Redis 源代码分配包含一个名为sentinel.conf这是一个自我记录的示例配置文件,您可以使用它来 配置 Sentinel,但典型的最小配置文件类似于 以后:

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

你只需要指定要监控的 master,给每个单独的 master (可能具有任意数量的副本)具有不同的名称。没有 需要指定副本,这些副本是自动发现的。Sentinel 将更新 配置,并自动提供有关副本的附加信息(在 以便在重新启动时保留信息)。配置为 在故障转移期间,每次将副本提升为主副本时,也会重写 以及每次发现新的 Sentinel 时。

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

的参数的含义sentinel monitorstatements 如下:

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

为了清楚起见,让我们逐行检查一下配置是什么 options 的意思是:

第一行用于告诉 Redis 监控一个名为 mymaster 的 master, 即地址 127.0.0.1 和端口 6379,仲裁为 2。万事 很明显,但 quorum 参数:

  • 仲裁是需要就 master 无法访问的事实达成一致的 Sentinel 数量,以便真正将 master 标记为失败,并最终在可能的情况下启动故障转移过程。
  • 但是,仲裁仅用于检测故障。为了实际执行故障转移,需要将其中一个 Sentinel 选为故障转移的领导者,并有权继续作。这仅在大多数 Sentinel 进程的投票中发生。

因此,例如,如果您有 5 个 Sentinel 进程,并且给定 master 设置为 2 的值,则情况如下:

  • 如果两个 Sentinel 同时就无法访问 master 达成一致,则两个 Sentinel 中的一个将尝试启动故障转移。
  • 如果总共至少有三个 Sentinel 可访问,则故障转移将获得授权并实际启动。

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

其他 Sentinel 选项

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

sentinel <option_name> <master_name> <option_value>

并用于以下目的:

  • down-after-milliseconds是实例不应 是可访问的(要么不回复我们的 PING,要么它回复了一个 错误),因为 Sentinel 开始认为它已关闭。
  • parallel-syncs设置可重新配置以使用 故障转移后的新 master 同时。数字越小, 故障转移过程需要更多时间才能完成,但是,如果 replicas 配置为提供旧数据,您可能不希望所有 replica 都 同时与 Master 重新同步。虽然复制 进程对于副本来说大多是非阻塞的,那么它会在某个时刻停止到 从 master 加载批量数据。您可能希望确保只有一个副本 通过将此选项设置为值 1 来无法访问。

本文档的其余部分介绍了其他选项,并且 在示例中记录sentinel.confRedis 附带的文件 分配。

可以在运行时修改配置参数:

  • 特定于主节点的配置参数使用SENTINEL SET.
  • 全局配置参数使用SENTINEL CONFIG SET.

有关更多信息,请参阅在运行时重新配置 Sentinel 部分

Sentinel 部署示例

既然您了解了 Sentinel 的基本信息,您可能想知道在哪里 您应该放置您的 Sentinel 进程,您需要多少个 Sentinel 进程 等等。本节介绍一些示例部署。

我们使用 ASCII 艺术以图形格式向您展示配置示例,这就是不同符号的含义:

+--------------------+
| This is a computer |
| or VM that fails   |
| independently. We  |
| call it a "box"    |
+--------------------+

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

+-------------------+
| Redis master M1   |
| Redis Sentinel S1 |
+-------------------+

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

+-------------+               +-------------+
| Sentinel S1 |---------------| Sentinel S2 |
+-------------+               +-------------+

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

+-------------+                +-------------+
| Sentinel S1 |------ // ------| Sentinel S2 |
+-------------+                +-------------+

另请注意:

  • 母版称为 M1、M2、M3、...、Mn。
  • 副本称为 R1、R2、R3、...、Rn(R 代表副本)。
  • 哨兵称为 S1、S2、S3、...、Sn。
  • 客户端称为 C1、C2、C3、...、Cn。
  • 当一个实例因为 Sentinel作而改变角色时,我们将其放在方括号内,所以 [M1] 表示一个实例由于 Sentinel 干预而成为主实例。

请注意,我们永远不会显示仅使用两个 Sentinel 的设置,因为 哨兵总是需要与大多数人交谈,以便开始 故障转移。

示例 1:只有两个 Sentinel,不要这样做

+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+

Configuration: quorum = 1
  • 在此设置中,如果主 M1 发生故障,则将提升 R1,因为两个 Sentinel 可以就故障达成协议(显然将 quorum 设置为 1),并且还可以授权故障转移,因为大多数是 2。所以显然它可以表面上工作,但是请检查接下来的几点,看看为什么这个设置被破坏了。
  • 如果运行 M1 的盒子停止工作,则 S1 也会停止工作。在另一个机箱 S2 中运行的 Sentinel 将无法授权故障转移,因此系统将不可用。

请注意,需要多数才能对不同的故障转移进行排序,然后将最新配置传播到所有 Sentinels。另请注意,在上述设置的单个端进行故障转移的能力,而没有任何协议,将非常危险:

+----+           +------+
| M1 |----//-----| [M1] |
| S1 |           | S2   |
+----+           +------+

在上面的配置中,我们创建了两个 master(假设 S2 可以故障转移 未经授权)以完全对称的方式进行。客户可以编写 无限期地传递给双方,并且无法理解何时 partition 修复正确的配置,以防止 永久性脑裂状况

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

示例 2:具有三个框的基本设置

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

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2

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

在每个 Sentinel 设置中,由于 Redis 使用异步复制,因此存在 总是有丢失一些写入的风险,因为给定的已确认写入 可能无法访问已提升为主副本的副本。然而,在 由于客户端被分区,上述设置存在更高的风险 与一位老主人,如下图所示:

         +----+
         | M1 |
         | S1 | <- C1 (writes will be lost)
         +----+
            |
            /
            /
+------+    |    +----+
| [M2] |----+----| R3 |
| S2   |         | S3 |
+------+         +----+

在这种情况下,网络分区隔离了旧的主 M1,因此 副本 R2 被提升为主副本。但是,客户端(如 C1)是 在与旧 master 相同的分区中,可以继续写入数据 对老主人。此数据将永远丢失,因为分区 将 heal,则 master 将被重新配置为新 master 的副本, 丢弃其数据集。

可以使用以下 Redis 复制来缓解此问题 功能,如果 Master 检测到 它无法再将其写入传输到指定数量的副本。

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

使用上述配置(请参阅自评redis.conf示例)当 Redis 实例充当主实例时,如果它无法写入至少 1 个副本,它将停止接受写入。由于复制是异步的,因此无法写入实际上意味着副本已断开连接,或者没有向我们发送超过指定max-lag秒数。

使用此配置,上述示例中的旧 Redis master M1 将在 10 秒后变得不可用。当分区修复时,Sentinel 配置将收敛到新配置,客户端 C1 将能够获取有效的配置并继续使用新的 master。

但是,天下没有免费的午餐。通过此优化,如果两个副本是 down,则 master 将停止接受写入。这是一种权衡。

示例 3:客户端框中的 Sentinel

有时我们只有两个 Redis 盒子可用,一个用于 master 和 一个用于副本。示例 2 中的配置在 这种情况,因此我们可以求助于以下内容,其中放置了 Sentinel 客户所在的位置:

            +----+         +----+
            | M1 |----+----| R1 |
            |    |    |    |    |
            +----+    |    +----+
                      |
         +------------+------------+
         |            |            |
         |            |            |
      +----+        +----+      +----+
      | C1 |        | C2 |      | C3 |
      | S1 |        | S2 |      | S3 |
      +----+        +----+      +----+

      Configuration: quorum = 2

在此设置中,视点 Sentinels 与客户端相同:如果 大多数客户都可以联系到主服务器,这很好。 这里的 C1、C2、C3 是泛型客户端,并不意味着 C1 标识 连接到 Redis 的单个客户端。它更像是这样的 一个应用程序服务器、一个 Rails 应用程序或类似的东西。

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

请注意,如果 C3 与 M1 进行分区(使用 网络,但更有可能使用不同的 layouts,或者由于软件层的故障),我们有一个类似的 问题,不同之处在于 没有办法打破对称性,因为只有一个 replica 和 master,所以 主服务器在与其副本断开连接时无法停止接受查询, 否则,在副本失败期间,主服务器将永远不可用。

因此,这是一个有效的设置,但示例 2 中的设置具有优势 比如 Redis 的 HA 系统运行在与 Redis 本身相同的盒子中 这可能更易于管理,并且能够对金额设置限制 少数分区中的主服务器可以接收写入作的时间。

示例 4:客户端少于 3 个

如果少于 客户端的三个框(例如三个 Web 服务器)。在这个 情况下,我们需要采用如下的混合设置:

            +----+         +----+
            | M1 |----+----| R1 |
            | S1 |    |    | S2 |
            +----+    |    +----+
                      |
               +------+-----+
               |            |
               |            |
            +----+        +----+
            | C1 |        | C2 |
            | S3 |        | S4 |
            +----+        +----+

      Configuration: quorum = 3

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

理论上,此设置可以删除运行 C2 和 S4 的框,并且 将 Quorum 设置为 2。但是,我们不太可能希望 HA 在 Redis 端,而我们的应用程序层中没有高可用性。

Sentinel、Docker、NAT 和可能的问题

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

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

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

  1. Sentinel 自动发现其他 Sentinel 不再有效,因为它基于 hello 消息,其中每个 Sentinel 都会宣布它们正在侦听的端口和 IP 地址进行连接。但是,Sentinel 无法理解地址或端口是否已重新映射,因此它会宣布一个不正确的信息,其他 Sentinel 无法连接。
  2. 副本列在INFORedis 主节点的输出以类似的方式:地址由主节点检查 TCP 连接的远程对等体检测到,而端口在握手期间由副本本身通告,但是端口可能由于与第 1 点中公开的相同原因而出错。

由于 Sentinels 使用 master 自动检测副本INFO输出信息, 将无法访问检测到的副本,并且 Sentinel 将永远无法访问 故障转移 Master,因为从 系统,因此目前没有办法用 Sentinel 监控一组 使用 Docker 部署的主实例和副本实例,除非您指示 Docker 以 1:1 映射端口

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

sentinel announce-ip <ip>
sentinel announce-port <port>

请注意,Docker 能够在主机网络模式下运行(检查--net=host选项了解更多信息)。这应该不会产生任何问题,因为在此设置中不会重新映射端口。

IP 地址和 DNS 名称

旧版本的 Sentinel 不支持在所有位置指定主机名和所需的 IP 地址。 从版本 6.2 开始,Sentinel 具有对主机名的可选支持。

默认情况下,此功能处于禁用状态。如果您要启用 DNS/主机名支持,请注意:

  1. Redis 和 Sentinel 节点上的名称解析配置必须可靠,并且能够快速解析地址。地址解析的意外延迟可能会对 Sentinel 产生负面影响。
  2. 您应该在所有位置使用主机名,并避免混合使用主机名和 IP 地址。为此,请使用replica-announce-ip <hostname>sentinel announce-ip <hostname>分别用于所有 Redis 和 Sentinel 实例。

启用resolve-hostnames全局配置允许 Sentinel 接受主机名:

  • 作为sentinel monitor命令
  • 作为副本地址,如果副本使用replica-announce-ip

Sentinel 将接受主机名作为有效输入并解析它们,但在宣布实例、更新配置文件等时仍会引用 IP 地址。

启用announce-hostnames全局配置使 Sentinel 改用主机名。这会影响对客户端的回复、配置文件中写入的值、REPLICAOF命令向副本发出,等等。

此行为可能与所有 Sentinel 客户端不兼容,这些客户端可能明确需要 IP 地址。

当客户端使用 TLS 连接到实例并需要名称而不是 IP 地址来执行证书 ASN 匹配时,使用主机名可能很有用。

快速教程

在本文档的后续部分中,有关 Sentinel API 的所有详细信息, 配置和语义将逐步介绍。然而,对于人们 想要尽快使用系统,本节是一个教程,其中显示了 如何配置 3 个 Sentinel 实例并与之交互。

这里我们假设实例在端口 5000、5001、5002 上执行。 我们还假设您在端口 6379 上有一个正在运行的 Redis 主节点,其 在端口 6380 上运行的副本。我们将使用 IPv4 环回地址 127.0.0.1 在本教程中无处不在,假设您正在运行模拟 在您的个人计算机上。

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

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

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

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

  • 主集称为mymaster.它标识 master 及其副本。由于每个主服务器集都有不同的名称,因此 Sentinel 可以同时监控不同的主服务器和副本服务器集。
  • 仲裁设置为值 2(sentinel monitorconfiguration 指令)。
  • down-after-milliseconds值为 5000 毫秒,即 5 秒,因此,一旦在此时间内没有收到 ping 的任何回复,主服务器就会被检测为失败。

启动三个 Sentinel 后,您会看到它们记录的一些消息,例如:

+monitor master mymaster 127.0.0.1 6379 quorum 2

这是一个 Sentinel 事件,您可以通过 Pub/Sub 接收此类事件 如果你SUBSCRIBE添加到稍后在 Pub/Sub 消息部分中指定的事件名称。

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

向 Sentinel 询问 Master 的状态

使用 Sentinel 开始,最明显的是检查 掌握 IT 正在监控 is doing well:

$ redis-cli -p 5000
127.0.0.1:5000> sentinel master mymaster
 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"

如您所见,它打印了有关 master 的许多信息。有 我们特别感兴趣的一些:

  1. num-other-sentinels是 2,因此我们知道 Sentinel 已经为这个 master 检测到了另外两个 Sentinel。如果您检查日志,您将看到+sentinel事件生成。
  2. flags只是master.如果主宰宕机,我们可以期待看到s_downo_down旗帜。
  3. num-slaves正确设置为 1,因此 Sentinel 还检测到有一个附加到 master 的副本。

为了了解有关此实例的更多信息,您可能需要尝试以下作 两个命令:

SENTINEL replicas mymaster
SENTINEL sentinels mymaster

第一个将提供有关连接到 master 的,第二个是关于其他哨兵的。

获取当前 master 的地址

正如我们已经指定的,Sentinel 还充当 想要连接到一组主副本的客户端。以 可能的故障转移或重新配置,客户端不知道谁是 给定实例集的当前活动主节点,因此 Sentinel 会导出 一个 API 来提出这个问题:

127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

测试故障转移

此时,我们的玩具 Sentinel 部署已准备好进行测试。我们可以 只需杀死我们的 master 并检查配置是否更改。要做到这一点 我们可以这样做:

redis-cli -p 6379 DEBUG sleep 30

此命令将使我们的 master 不再可访问,休眠 30 秒。 它基本上模拟了出于某种原因的母版挂起。

如果您检查 Sentinel 日志,您应该能够看到很多作:

  1. 每个 Sentinel 都会检测到 master 已关闭,并带有+sdown事件。
  2. 此事件稍后会升级为+odown,这意味着多个 Sentinel 都同意无法访问 master 的事实。
  3. Sentinel 投票选出一个 Sentinel,该 Sentinel 将启动第一次故障转移尝试。
  4. 故障转移发生。

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

127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6380"

目前为止,一切都好。。。此时,您可以跳转到 创建 Sentinel 部署 或者可以阅读更多内容来了解所有 Sentinel 命令和内部结构。

Sentinel API

Sentinel 提供了一个 API 来检查其状态,检查运行状况 的受监控 master 和 replica 的 master 和 replica 中,订阅以接收特定的 通知,并在运行时更改 Sentinel 配置。

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

可以直接查询 Sentinel 来检查 从其角度监控的 Redis 实例,以查看其他 它知道哨兵,依此类推。或者,使用 Pub/Sub 也可以 接收来自 Sentinel 的推送式通知,每次发生某些事件时 发生,例如故障转移或实例进入错误条件,以及 等等。

Sentinel 命令

SENTINELcommand 是 Sentinel 的主要 API。以下是其子命令的列表(在适用的情况下,会注明最低版本):

  • SENTINEL CONFIG GET<name> (>= 6.2) 获取全局 Sentinel 配置参数的当前值。指定的名称可以是通配符,类似于 RedisCONFIG GET命令。
  • SENTINEL 配置集<name> <value> (>= 6.2) 设置全局 Sentinel 配置参数的值。
  • SENTINEL CKQUORUM<master name>检查当前 Sentinel 配置是否能够达到故障转移主服务器所需的仲裁,以及授权故障转移所需的大多数。此命令应用于监控系统,以检查 Sentinel 部署是否正常。
  • SENTINEL FLUSHCONFIG强制 Sentinel 在磁盘上重写其配置,包括当前 Sentinel 状态。通常,每当其状态发生更改时,Sentinel 都会重写配置(在重启时保留在磁盘上的状态子集的上下文中)。但是,有时配置文件可能会因作错误、磁盘故障、软件包升级脚本或配置管理器而丢失。在这些情况下,强制 Sentinel 重写配置文件的方法是很方便的。即使前面的配置文件完全缺失,此命令也有效。
  • SENTINEL 故障转移<master name>强制故障转移,就好像无法访问主服务器一样,并且不征求其他 Sentinel 的同意(但是,将发布新版本的配置,以便其他 Sentinel 更新其配置)。
  • SENTINEL GET-MASTER-ADDR-BY-NAME<master name>返回具有该名称的主服务器的 ip 和端口号。如果此主节点的故障转移正在进行或已成功终止,则返回已提升副本的地址和端口。
  • SENTINEL INFO-CACHE (>= 3.2) 返回缓存的INFO来自 master 和 replica 的输出。
  • SENTINEL IS-MASTER-DOWN-BY-ADDR 从当前 Sentinel 的角度来看,检查 ip:port 指定的 master 是否宕机。此命令主要供内部使用。
  • 哨兵大师<master name>显示指定 master 的状态和信息。
  • 哨兵大师显示受监控的 master 及其状态的列表。
  • 哨兵监视器启动 Sentinel 的监控。有关更多信息,请参阅在运行时重新配置 Sentinel 部分
  • 哨兵 MYID (>= 6.2) 返回 Sentinel 实例的 ID。
  • SENTINEL 待处理脚本此命令返回有关待处理脚本的信息。
  • 哨兵移除停止 Sentinel 的监控。有关更多信息,请参阅在运行时重新配置 Sentinel 部分
  • SENTINEL 副本<master name> (>= 5.0) 显示此 master 的副本列表及其状态。
  • 哨兵<master name>显示此 master 的 sentinel 实例列表及其状态。
  • 哨兵套装设置 Sentinel 的监控配置。有关更多信息,请参阅在运行时重新配置 Sentinel 部分
  • SENTINEL SIMULATE-FAILURE (选举后崩溃|提升后崩溃|帮助) (>= 3.2) 此命令模拟不同的 Sentinel 崩溃场景。
  • 哨兵重置<pattern>此命令将重置所有具有匹配名称的 master。pattern 参数是 glob 样式的模式。重置过程会清除主服务器中的任何先前状态(包括正在进行的故障转移),并删除已发现并与主服务器关联的每个副本和 sentinel。

出于连接和管理目的,Sentinel 支持以下 Redis 命令的子集:

  • ACL (前交叉韧带) (>= 6.2) 此命令管理 Sentinel 访问控制列表。有关更多信息,请参阅 ACL 文档页面和 Sentinel 访问控制列表鉴定
  • 认证 (>= 5.0.1) 对客户端连接进行身份验证。有关更多信息,请参阅AUTH命令和使用身份验证配置 Sentinel 实例部分
  • 客户此命令管理客户端连接。有关更多信息,请参阅其子命令的页面。
  • 命令 (>= 6.2) 此命令返回有关命令的信息。有关更多信息,请参阅COMMANDcommand 及其各种子命令。
  • 你好 (>= 6.0) 切换连接的协议。有关更多信息,请参阅HELLO命令。
  • 信息返回有关 Sentinel 服务器的信息和统计信息。有关更多信息,请参阅INFO命令。
  • 此命令仅返回 PONG。
  • 角色此命令返回字符串 “sentinel” 和受监控的 master 列表。有关更多信息,请参阅ROLE命令。
  • 关闭关闭 Sentinel 实例。

最后,Sentinel 还支持SUBSCRIBE,UNSUBSCRIBE,PSUBSCRIBEPUNSUBSCRIBE命令。有关更多详细信息,请参阅 Pub/Sub 消息部分

在运行时重新配置 Sentinel

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

以下是SENTINEL用于更新 Sentinel 实例的配置的子命令。

  • 哨兵监视器<name> <ip> <port> <quorum>此命令指示 Sentinel 开始监控具有指定名称、IP、端口和 quorum 的新主服务器。它与sentinel monitorconfiguration 指令sentinel.conf配置文件,不同之处在于您不能在 AS 中使用主机名ip,但您需要提供 IPv4 或 IPv6 地址。
  • 哨兵移除<name>用于删除指定的 master:该 master 将不再受到监控,并且将完全从 Sentinel 的内部状态中删除,因此它将不再由SENTINEL masters等等。
  • 哨兵套装<name> [<option> <value>...]SET 命令与CONFIG SET命令,用于更改特定 master 的配置参数。可以指定多个选项/值对(或根本不指定)。所有配置参数均可通过sentinel.conf也可以使用 SET 命令进行配置。

以下是SENTINEL SET命令以修改down-after-milliseconds名为objects-cache:

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

如前所述,SENTINEL SET可用于设置可在 startup 配置文件中设置的所有配置参数。此外,可以只更改 master 仲裁配置,而无需使用SENTINEL REMOVE其次SENTINEL MONITOR,但只需使用:

SENTINEL SET objects-cache-master quorum 5

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

从 Redis 版本 6.2 开始,Sentinel 还允许获取和设置全局配置参数,这些参数仅在之前的配置文件中受支持。

  • SENTINEL CONFIG GET<name>获取全局 Sentinel 配置参数的当前值。指定的名称可以是通配符,类似于 RedisCONFIG GET命令。
  • SENTINEL 配置集<name> <value>设置全局 Sentinel 配置参数的值。

可以作的全局参数包括:

添加或删除 Sentinel

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

如果您需要一次添加多个 Sentinel,建议添加它 一个接一个,等待所有其他哨兵已经知道 在添加下一个之前。这对于仍然 保证只能在分区的一侧实现多数, 在添加新 Sentinel 的过程中可能会发生故障。

这可以通过添加每个新的 Sentinel 来轻松实现,延迟 30 秒,并且在没有网络分区的情况下。

在该过程结束时,可以使用命令SENTINEL MASTER mastername为了检查是否所有 Sentinels 都同意 监视主节点的 Sentinel 总数。

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

  1. 停止要删除的 Sentinel 的 Sentinel 进程。
  2. 发送SENTINEL RESET *命令分配给所有其他 Sentinel 实例(如果您只想重置一个 Master,则可以使用确切的 Master 名称)。一个接一个,实例之间至少等待 30 秒。*
  3. 通过检查SENTINEL MASTER mastername每个哨兵。

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

哨兵永远不会忘记给定主服务器的副本,即使它们是 长时间无法访问。这很有用,因为 Sentinels 应该能够 要在网络分区或 failure 事件。

此外,在故障转移之后,故障转移的 master 实际上被添加为 replica 的 Replica 中,这样它将被重新配置为使用 新的 master 将再次可用。

但是,有时您想要删除副本(可能是旧的主副本) forever 从 Sentinel 监控的副本列表中。

为此,您需要发送一个SENTINEL RESET mastername命令 到所有 Sentinels:他们将在下一个 10 秒,仅添加列为从 当前主服务器INFO输出。

Pub/Sub 消息

客户端可以将 Sentinel 用作与 Redis 兼容的 Pub/Sub 服务器 (但您不能使用PUBLISH) 以便SUBSCRIBEPSUBSCRIBE自 频道,并获取有关特定事件的通知。

频道名称与事件名称相同。例如, 频道名称+sdown将收到与实例相关的所有通知 输入SDOWN(SDOWN 表示无法再从该实例访问 您正在查询的 Sentinel 的视点)条件。

要获取所有消息,只需使用PSUBSCRIBE *.

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

注意:如果指定了 instance details,则表示提供了以下参数来标识目标实例:

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

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

  • +重置主站 <instance details>-- 主服务器已重置。
  • +奴隶 <instance details>-- 检测到并附加了新副本。
  • +failover-state-reconf-slaves <instance details>-- 故障转移状态更改为reconf-slaves州。
  • 检测到 +failover-detected <instance details>-- 检测到由另一个 Sentinel 或任何其他外部实体启动的故障转移(附加的副本变成了主节点)。
  • +slave-reconf-sent <instance details>-- 领导哨兵发送了REPLICAOF命令添加到此实例,以便为新副本重新配置它。
  • +slave-reconf-inprog <instance details>-- 正在重新配置的副本显示为新主 ip:port 对的副本,但同步过程尚未完成。
  • +slave-reconf-done <instance details>-- 副本现在已与新的主服务器同步。
  • -dup-哨兵 <instance details>-- 指定 master 的一个或多个 Sentinel 被删除为重复项(例如,当 Sentinel 实例重新启动时,会发生这种情况)。
  • +哨兵 <instance details>-- 检测到并附加了此主服务器的新 sentinel。
  • +sdown <instance details>-- 指定的实例现在处于 Subjectively Down 状态。
  • -sdown <instance details>-- 指定的实例不再处于 Subjectively Down 状态。
  • +odown <instance details>-- 指定的实例现在处于 Objectively Down 状态。
  • -odown <instance details>-- 指定的实例不再处于 Objectively Down 状态。
  • +新纪元 <instance details>-- 当前 epoch 已更新。
  • +try-failover <instance details>-- 新的故障转移正在进行中,等待多数人选举。
  • +当选领导者 <instance details>-- 赢得指定 epoch 的选举,可以进行故障转移。
  • +failover-state-select-slave <instance details>-- 新的故障转移状态为select-slave:我们正在努力寻找合适的复制品进行促销。
  • 不好的奴隶 <instance details>-- 没有好的复制品可以推广。目前,我们将在一段时间后尝试,但这可能会发生变化,在这种情况下,状态机将完全中止故障转移。
  • selected-slave (已选择从属) <instance details>-- 我们找到了要推广的指定 Good Replica。
  • failover-state-send-slaveof-noone <instance details>-- 我们正在尝试将提升的副本重新配置为 master,等待它切换。
  • 故障转移结束超时 <instance details>-- 故障转移因超时而终止,副本最终将配置为使用新的主服务器进行复制。
  • failover-end (故障转移结束) <instance details>-- 故障转移成功终止。所有副本似乎都已重新配置为使用新的主服务器进行复制。
  • 开关主站 <master name> <oldip> <oldport> <newip> <newport>-- 主 new IP 和地址是配置更改后指定的 IP 和地址。这是大多数外部用户感兴趣的消息
  • +tilt -- 进入倾斜模式。
  • -tilt -- 退出倾斜模式。

处理 -BUSY 状态

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

如果实例在此尝试后仍处于错误状态,它将 最终被故障转移。

副本优先级

Redis 实例有一个名为replica-priority. 此信息由 Redis 副本实例在其INFO输出 Sentinel 使用它来从可以 用于故障转移主服务器:

  1. 如果 replica 优先级设置为 0,则 replica 永远不会提升为 master。
  2. Sentinel 首选优先级编号较低的副本。

例如,如果当前 master 和另一个数据中心的另一个副本 S2 时,可以设置 优先级为 10 的 S1 和优先级为 100 的 S2,因此,如果 master 失败,并且 S1 和 S2 都可用,则首选 S1。

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

Sentinel 和 Redis 身份验证

当 master 配置为需要客户端的身份验证时, 作为一项安全措施,副本还需要了解 order 向 master 进行身份验证并创建 master-replica 连接 用于异步复制协议。

Redis 访问控制列表身份验证

从 Redis 6 开始,用户身份验证和权限使用访问控制列表 (ACL) 进行管理。

为了让 Sentinel 在以下情况下连接到 Redis 服务器实例 配置了 ACL,则 Sentinel 配置必须包含 以下指令:

sentinel auth-user <master-name> <username>
sentinel auth-pass <master-name> <password>

哪里<username><password>是用于访问组实例的用户名和密码。应在组的所有 Redis 实例上预置这些凭证,并具有最低控制权限。例如:

127.0.0.1:6379> ACL SETUSER sentinel-user ON >somepassword allchannels +multi +slaveof +ping +exec +subscribe +config|rewrite +role +publish +info +client|setname +client|kill +script|kill

Redis 仅密码身份验证

在 Redis 6 之前,使用以下配置指令实现身份验证:

  • requirepass在 master 中,为了设置身份验证密码,并确保实例不会处理未经身份验证的客户端的请求。
  • masterauth在副本中,以便副本能够向 master 进行身份验证,以便从中正确复制数据。

使用 Sentinel 时,没有单个主服务器,因为在故障转移之后 副本可以扮演 master 的角色,旧的 master 可以在 order 作为副本,所以你要做的是设置上面的指令 在您的所有实例中,包括 Master 和 Replicas。

这通常也是一种合理的设置,因为您不想保护 data only in the master,在副本中具有相同的数据。

但是,在极少数情况下,您需要一个可访问的副本 在没有身份验证的情况下,您仍然可以通过设置副本优先级来执行此作 为零,以防止此副本被提升为主副本,以及 在此副本中仅配置masterauth指令,不带 使用requirepass指令,以便数据可被 未经身份验证的客户端。

为了让 Sentinel 在以下情况下连接到 Redis 服务器实例 配置了requirepass,则 Sentinel 配置必须包含sentinel auth-pass指令,格式为:

sentinel auth-pass <master-name> <password>

使用身份验证配置 Sentinel 实例

可以通过要求客户端通过AUTH命令。从 Redis 6.2 开始,可以使用访问控制列表 (ACL),而以前的版本(从 Redis 5.0.1 开始)支持仅密码身份验证。

请注意,Sentinel 的身份验证配置应应用于部署中的每个实例,并且所有实例都应使用相同的配置。此外,ACL 和仅密码身份验证不应一起使用。

Sentinel 访问控制列表认证

使用 ACL 保护 Sentinel 实例的第一步是防止任何未经授权的访问。为此,您需要禁用默认超级用户(或至少使用强密码对其进行设置)并创建一个新超级用户并允许其访问 Pub/Sub 频道:

127.0.0.1:5000> ACL SETUSER admin ON >admin-password allchannels +@all
OK
127.0.0.1:5000> ACL SETUSER default off
OK

Sentinel 使用默认用户连接到其他实例。您可以使用以下配置指令为另一个超级用户的凭证提供:

sentinel sentinel-user <username>
sentinel sentinel-pass <password>

哪里<username><password>分别是 Sentinel 的超级用户和密码(例如adminadmin-password在上面的示例中)。

最后,为了验证传入的客户端连接,您可以创建 Sentinel 受限用户配置文件,如下所示:

127.0.0.1:5000> ACL SETUSER sentinel-user ON >user-password -@all +auth +client|getname +client|id +client|setname +command +hello +ping +role +sentinel|get-master-addr-by-name +sentinel|master +sentinel|myid +sentinel|replicas +sentinel|sentinels +sentinel|masters

有关详细信息,请参阅所选 Sentinel 客户端的文档。

Sentinel 仅密码身份验证

要将 Sentinel 与仅密码身份验证一起使用,请添加requirepassconfiguration 指令添加到所有 Sentinel 实例中,如下所示:

requirepass "your_password_here"

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

  1. 需要客户端提供密码才能向 Sentinel 发送命令。这是显而易见的,因为这就是这种配置指令在 Redis 中通常的工作方式。
  2. 此外,此 Sentinel 实例将使用配置为访问本地 Sentinel 的相同密码来验证它所连接的所有其他 Sentinel 实例。

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

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

Sentinel 客户端实施


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

更高级的概念

在以下部分中,我们将介绍有关 Sentinel 工作原理的一些详细信息: 而无需求助于将要 在本文档的最后一部分介绍。

SDOWN 和 ODOWN 失败状态

Redis Sentinel 有两种不同的宕机概念,一种称为 主观上为 Down 条件 (SDOWN),并且是 local 添加到给定的 Sentinel 实例。另一个称为客观关闭条件 (ODOWN),当有足够的 Sentinel(至少 number 配置为quorum参数)具有 SDOWN 条件,并使用 这SENTINEL is-master-down-by-addr命令。

从 Sentinel 的角度来看,当 SDOWN 条件 在秒数内未收到对 PING 请求的有效回复 在配置中指定为is-master-down-after-milliseconds参数。

对 PING 的可接受回复是以下之一:

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

任何其他回复(或根本没有回复)都被视为无效。 但是请注意,在 INFO 输出被视为已关闭

请注意,SDOWN 要求整个 interval 配置,例如,如果 interval 为 30000 毫秒 (30 秒),并且我们每 29 秒收到一次可接受的 ping 回复,则 实例被视为正在工作。

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

要从 SDOWN 切换到 ODOWN,没有使用强共识算法,但 只是一种八卦形式:如果给定的 Sentinel 收到报告,则 master 在给定时间范围内没有从足够的 Sentinel 工作,则 SDOWN 为 晋升为 ODOWN。如果以后缺少此确认,则会清除该标志。

在 才能真正启动故障转移,但如果没有 达到 ODOWN 状态。

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

但是,SDOWN 也具有语义含义。例如,SDOWN 中的副本 state 未被选中由执行故障转移的 Sentinel 提升。

哨兵和副本自动发现

哨兵与其他哨兵保持联系,以便相互 检查彼此的可用性,并交换消息。但是 不需要在每个 Sentinel 中配置其他 Sentinel 地址的列表 实例,因为 Sentinel 使用 Redis 实例 Pub/Sub 功能 为了发现监控相同主服务器的其他 Sentinel 和副本。

此功能是通过向名为__sentinel__:hello.

同样,您不需要配置附加的副本列表 复制到 master,因为 Sentinel 会自动发现查询 Redis 的这个列表。

  • 每个 Sentinel 都会向每个受监控的主 Pub/Sub 通道发布一条消息__sentinel__:hello,每两秒一次,使用 ip、port、runid 宣布其存在。
  • 每个 Sentinel 都订阅了 Pub/Sub 频道__sentinel__:hello每个主副本和副本,寻找未知的哨兵。当检测到新的 Sentinel 时,它们将被添加为此主控服务器的 Sentinel。
  • Hello 消息还包括 master 的完整当前配置。如果接收 Sentinel 的给定 master 的配置早于接收的配置,则它会立即更新为新配置。
  • 在向 master 添加新的 sentinel 之前,Sentinel 总是会检查是否已经有具有相同 runid 或相同地址(ip 和 port 对)的 sentinel。在这种情况下,将删除所有匹配的 sentinel,并添加新的 sentinel。

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

即使没有进行故障转移,Sentinel 也始终会尝试将 受监控实例上的当前配置。具体说来:

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

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

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

还要注意,总是尝试施加当前配置的语义如何使故障转移对分区更具抵抗力:

  • 故障转移的主节点在返回可用时被重新配置为副本。
  • 在分区期间分区的副本在可访问后将重新配置。

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

副本选择和优先级

当 Sentinel 实例准备好执行故障转移时,由于 master 在ODOWNstate 和 Sentinel 收到故障转移的授权 从大多数已知的 Sentinel 实例中,合适的副本需要 以被选中。

副本选择过程评估有关副本的以下信息:

  1. 与 master 的断开连接时间。
  2. 副本优先级。
  3. 已处理复制偏移量。
  4. 运行 ID。

发现与 master 断开连接超过 10 个的副本 乘以配置的 master timeout (down-after-milliseconds 选项),加上 从主时间的角度来看,主服务器也不可用 执行故障转移的 Sentinel 被认为不适合故障转移 并被跳过。

更严格地说,其INFO输出表明它已经 与 Master 断开连接的时间超过:

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

被认为不可靠,完全无视。

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

  1. 副本按replica-priorityredis.conf文件。优先级较低者优先。
  2. 如果优先级相同,则检查 replica 处理的 replication offset,并选择从 master 接收更多数据的副本。
  3. 如果多个副本具有相同的优先级并处理来自主节点的相同数据,则会执行进一步检查,选择运行编号较小的副本。对于副本来说,具有较低的运行 ID 并不是真正的优势,但对于使副本选择过程更具确定性(而不是求助于选择随机副本)非常有用。

在大多数情况下,replica-priority不需要显式设置,因此所有 实例将使用相同的默认值。如果存在特定的故障转移 偏好replica-priority必须在所有实例上设置,包括 masters、 因为 master 可能会在未来的某个时间点成为副本 - 然后它将 需要适当的replica-priority设置。

Redis 实例可以配置特殊的replica-priority为零 这样就不会被 Sentinel 为新的主控器。 但是,以这种方式配置的副本仍将由 Sentinels 为了在故障转移后使用新的 master 进行复制, 唯一的区别是它本身永远不会成为 Master。

算法和内部原理

在以下部分中,我们将探讨 Sentinel 行为的详细信息。 用户并不严格需要了解所有细节,但 对 Sentinel 的深入了解可能有助于在 一种更有效的方法。

法定人数

前面的部分显示了 Sentinel 监控的每个 master 都与配置的 quorum 相关联。它指定 Sentinel 进程的数量 需要就 Master 的 unreachability 或 error 条件达成一致 order 触发故障转移。

但是,在触发故障转移后,为了实际执行故障转移,至少大多数 Sentinel 必须授权 Sentinel 执行 故障转移。Sentinel 从不在 少数哨兵存在。

让我们试着把事情说得更清楚一点:

  • Quorum:需要检测错误情况才能将主节点标记为 ODOWN 的 Sentinel 进程数。
  • 故障转移由 ODOWN 状态触发。
  • 触发故障转移后,尝试故障转移的 Sentinel 需要请求对大多数 Sentinel 的授权(如果仲裁设置为大于多数的数字,则请求超过多数)。

这种差异可能看起来很微妙,但实际上很容易理解和使用。例如,如果您有 5 个 Sentinel 实例,并且仲裁设置为 2,则只要 2 个 Sentinel 认为无法访问主实例,就会触发故障转移,但是,两个 Sentinel 中的一个只有在至少获得 3 个 Sentinel 的授权时才能进行故障转移。

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

这意味着 quorum 可用于通过两种方式调整 Sentinel:

  1. 如果 quorum 设置为小于我们部署的大多数 Sentinel 的值,我们基本上是使 Sentinel 对 master 故障更加敏感,一旦只有少数 Sentinel 无法再与 master 通信,就会触发故障转移。
  2. 如果 quorum 设置为大于大多数 Sentinel 的值,则只有当有非常多(大于大多数)连接良好的 Sentinel 同意主服务器关闭时,我们才会使 Sentinel 能够进行故障转移。

配置 epoch

Sentinels 需要获得大多数人的授权才能启动 故障转移有几个重要原因:

当 Sentinel 获得授权时,它会获得它正在故障转移的主服务器的唯一配置 epoch。此数字将用于在故障转移完成后对新配置进行版本控制。由于大多数人都同意将给定版本分配给给定的 Sentinel,因此其他 Sentinel 将无法使用它。这意味着每个故障转移的每个配置都使用唯一的版本进行版本控制。我们将了解为什么这如此重要。

此外,Sentinel 有一个规则:如果一个 Sentinel 投票给另一个 Sentinel 来对给定的主节点进行故障转移,它将等待一段时间,然后再次尝试对同一个主节点进行故障转移。此延迟是2 * failover-timeout您可以在sentinel.conf.这意味着 Sentinels 不会同时尝试故障转移同一个 Master,第一个请求授权的 Master 将尝试,如果失败,另一个 TSentinel 将在一段时间后尝试,依此类推。

Redis Sentinel 保证活动性属性,如果大多数 Sentinel 能够通信,最终如果 master 宕机,其中一个 Sentinel 将被授权进行故障转移。

Redis Sentinel 还保证每个 Sentinel 将使用不同的配置 epoch 对同一 master 进行故障转移的安全属性。

配置传播

一旦 Sentinel 能够成功故障转移 Master,它将开始广播新配置,以便其他 Sentinel 更新有关给定 Master 的信息。

要使故障转移被视为成功,它要求 Sentinel 能够将REPLICAOF NO ONE命令添加到所选副本中,并且稍后会在INFOmaster 的输出。

此时,即使副本的重新配置正在进行中,故障转移也被视为成功,并且所有 Sentinel 都需要开始报告新配置。

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

每个 Sentinel 都使用 Redis Pub/Sub 消息在 master 和所有副本中持续广播其 master 的配置版本。同时,所有 Sentinel 都在等待消息,以查看配置是什么 由其他哨兵做广告。

配置在__sentinel__:helloPub/Sub 频道。

由于每个配置都有不同的版本号,因此版本更高 总是胜过较小的版本。

因此,例如,master 的配置mymaster从所有 哨兵认为主服务器位于 192.168.1.50:6379。此配置 具有版本 1。一段时间后,Sentinel 被授权使用版本 2 进行故障转移。如果故障转移成功,它将开始广播新配置,比如 192.168.1.50:9000,版本 2。所有其他实例都将看到此配置,并相应地更新其配置,因为新配置具有更高的版本。

这意味着 Sentinel 保证第二个活动属性:一组 能够通信的 Sentinel 都将收敛到具有较高版本号的相同配置。

基本上,如果 net 是分区的,则每个分区都会收敛到更高的 本地配置。在没有分区的特殊情况下,只有一个 partition 的 Bean 和每个 Sentinel 都会就配置达成一致。

分区下的一致性

Redis Sentinel 配置是最终一致的,因此每个分区都将 收敛到可用的更高配置。 但是,在使用 Sentinel 的实际系统中,有三种不同的参与者:

  • Redis 实例。
  • Sentinel 实例。
  • 客户。

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

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

            +-------------+
            | Sentinel 1  |----- Client A
            | Redis 1 (M) |
            +-------------+
                    |
                    |
+-------------+     |          +------------+
| Sentinel 2  |-----+-- // ----| Sentinel 3 |----- Client B
| Redis 2 (S) |                | Redis 3 (M)|
+-------------+                +------------+

在这个系统中,原始状态是 Redis 3 是 master,而 Redis 1 和 2 是副本。发生隔离旧主控的分区。 Sentinels 1 和 2 启动了故障转移,将 Sentinel 1 提升为新的主服务器。

Sentinel 属性保证 Sentinel 1 和 2 现在具有新的 master 的配置。但是,Sentinel 3 仍然具有旧配置 因为它位于不同的分区中。

我们知道,当网络 partition 将修复,但是如果存在 客户端是否使用旧主服务器进行分区?

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

根据您的配置,您可能希望或不希望发生此方案:

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

由于 Redis 是异步复制的,因此在这种情况下无法完全防止数据丢失,但是您可以限制 Redis 3 和 Redis 1 之间的分歧 使用以下 Redis 配置选项:

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

使用上述配置(请参阅自评redis.conf示例)当 Redis 实例充当主实例时,如果它无法写入至少 1 个副本,它将停止接受写入。由于复制是异步的,因此无法写入实际上意味着副本已断开连接,或者没有向我们发送超过指定max-lag秒数。

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

一般来说,Redis + Sentinel 作为一个整体是一个最终一致的系统,其中合并功能是最后一次故障转移获胜,并且来自旧 master 的数据被丢弃以复制当前 master 的数据,因此总会有一个丢失已确认写入的窗口。这是由于 Redis 异步的 复制和系统的 “虚拟” 合并功能的丢弃性质。请注意,这不是 Sentinel 本身的限制,如果您使用强一致性复制状态机编排故障转移,则相同的属性仍将适用。只有两种方法可以避免丢失已确认的写入:

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

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

Sentinel 持久状态

Sentinel 状态保留在 Sentinel 配置文件中。例如 每次收到或创建新配置(leader Sentinels)时,对于 主服务器,则配置将与配置一起保存在磁盘上 时代。这意味着停止和重新启动 Sentinel 进程是安全的。

TILT 模式

Redis Sentinel 严重依赖于计算机时间:例如在 order 来了解实例是否可用,它会记住 latest 成功回复 PING 命令,并将其与当前的 是时候了解它有多老了。

但是,如果计算机时间以意外方式更改,或者如果计算机 非常繁忙,或者进程由于某种原因被阻止,Sentinel 可能会开始 以意想不到的方式行事。

TILT 模式是一种特殊的 “保护” 模式,Sentinel 可以在 检测到一些奇怪的东西,可能会降低系统的可靠性。 Sentinel 计时器中断通常每秒调用 10 次,因此我们 预计两次调用之间将经过或多或少 100 毫秒 拖动到计时器中断。

Sentinel 所做的是注册计时器中断的上一次 ,并将其与当前调用进行比较:如果 为负数或意外大(2 秒或更长时间),则进入 TILT 模式 (或者如果已经进入,则推迟退出 TILT 模式)。

当处于 TILT 模式时,Sentinel 将继续监控所有内容,但是:

  • 它完全停止行动。
  • 它开始对SENTINEL is-master-down-by-addr请求,因为检测故障的能力不再受信任。

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

在 Sentinel TILT 模式下,如果我们发送 INFO 命令,我们可以得到以下响应:

$ redis-cli -p 26379
127.0.0.1:26379> info
(Other information from Sentinel server skipped.)

# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_tilt_since_seconds:-1
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=0,sentinels=1

字段 “sentinel_tilt_since_seconds” 表示 Sentinel 已经处于 TILT 模式的秒数。 如果它不在 TILT 模式下,则该值将为 -1。

请注意,在某些方面,可以使用单调时钟来代替 TILT 模式 API 中。然而,目前尚不清楚这是否是一个好的 解决方案,因为当前的系统避免了问题,以防该过程只是 已暂停或长时间未被调度器执行。

关于本手册页中使用的单词 slave 的说明:从 Redis 5 开始,如果不是为了向后兼容,Redis 项目不再使用单词 slave。不幸的是,在这个命令中,slave 这个词是协议的一部分,所以只有当这个 API 被自然弃用时,我们才能删除此类事件。

为本页评分
返回顶部 ↑