Redis【有与无】【Admin-11】Redis Sentinel文档(高可用性)

本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。

目录

1.Redis Sentinel

1.1.Sentinel的分布式性质

1.2.快速开始

1.2.1.获取Sentinel

1.2.2.运行Sentinel

1.2.3部署前有关Sentinel的基本知识

1.2.4.配置Sentinel

1.2.5.其他Sentinel选项

1.2.6.Sentinel部署示例

示例1:仅两个Sentinels,DON'T DO THIS

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

示例3:客户端盒子中的Sentinel

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

1.2.7.Sentinel,Docker,NAT和可能的问题

1.3.快速教程

1.3.1.向Sentinel询问主节点状态

1.3.2.获取当前主节点的地址

1.3.3.测试故障转移

1.4.Sentinel API

1.4.1.Sentinel命令

1.4.2.在运行时重新配置Sentinel

1.4.3.添加或删除哨兵(Sentinels)

1.4.4.删除旧的主节点或无法访问的复制节点

1.4.5.发布/订阅(Pub/Sub)消息

1.4.6.处理-BUSY状态

1.4.7.复制节点(Replicas)优先级

1.4.8.Sentinel和Redis身份验证

1.4.9.Redis访问控制列表认证

1.4.10.使用身份验证配置Sentinel实例

1.4.11.Sentinel访问控制列表身份验证

1.4.12.Sentinel仅密码身份验证

1.4.13.Sentinel客户实现

1.5.更高级的概念

1.5.1.DOWN和DOWN故障状态

1.5.2.Sentinel和复制节点(replicas )自动发现

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

1.5.4.复制节点选择和优先级

1.6.算法和内部

1.6.1.Quorum(仲裁数)

1.6.2.配置时代(epochs)

1.6.3.配置传播(propagation)

1.6.4.分区下的一致性

1.6.5.Sentinel持久化状态

1.6.6.TILT模式


1.Redis Sentinel

Redis Sentinel为Redis提供高可用性。 实际上,这意味着使用Sentinel可以创建Redis部署,该部署可以在无需人工干预的情况下抵抗某些类型的故障。

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

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

  • Monitoring(监控方式). Sentinel会不断检查你的主节点实例和复制节点实例是否按预期工作。
  • Notification(通知). Sentinel可以通过API通知系统管理员或其他计算机程序,其中一个受监视的Redis实例出了问题。
  • Automatic failover(自动故障转移). 如果主节点未按预期工作,则Sentinel可以启动故障转移过程,在该过程中将复制节点升级为主节点,将其他复制节点复制为使用新主节点,并当连接时,通知使用Redis服务器的应用程序要使用的新地址。
  • Configuration provider(配置提供者). Sentinel充当客户端服务发现的授权来源:客户端连接到Sentinels,以询问负责给定服务的当前Redis主节点的地址。 如果发生故障转移,Sentinels将报告新地址。

1.1.Sentinel的分布式性质

Redis Sentinel是一个分布式系统:

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

  1. 当多个哨兵就给定的主节点不再可用这一事实达成共识时,将执行故障检测。 这降低了误报的可能性。
  2. 即使不是所有的Sentinel进程都在工作,Sentinel仍能正常工作,从而使系统能够应对故障。 毕竟,拥有故障转移系统本身就是一个单点故障,这没有任何乐趣。

Sentinels【Redis实例(主节点和复制节点)以及连接到Sentinel和Redis的客户端】的总和也是具有特定属性的大型分布式系统。 在本文档中,将逐步介绍概念,从为了理解Sentinel的基本属性所需的基本信息,到为了理解Sentinel的工作原理的更复杂的信息(可选)。

1.2.快速开始

1.2.1.获取Sentinel

Sentinel的当前版本称为Sentinel 2。它是使用更强大且更易于预测的算法(在本文档中进行说明)对Sentinel初始实现进行的重写。

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

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

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

1.2.2.运行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正常工作,必须打开服务器的端口26379,以接收来自其他Sentinel实例的IP地址的连接。 否则,Sentinels无法交流也不能就该做什么达成一致,因此将永远不会执行故障转移。

1.2.3部署前有关Sentinel的基本知识

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

1.2.4.配置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

你只需要指定要监视的主节点,即可为每个单独的主节点(可以有多个复制节点)指定一个不同的名称。 无需指定自动发现的复制节点。 Sentinel将使用有关复制节点的其他信息自动更新配置(以便在重新启动时保留该信息)。 每次在故障转移期间将复制节点提升为主节点时,以及每次发现新的Sentinel时,都会重写配置。

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

sentinel monitor 语句的参数含义如下:

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

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

第一行用于告诉Redis监视名为mymaster的主服务器,该主服务器的地址为127.0.0.1和端口6379,quorum 为2。

  • quorum 是需要就主节点不可访问这一事实达成共识的Sentinel的数量,以便将主节点真正标记为发生故障,并在可能的情况下最终启动故障转移过程。
  • 但是,quorum 仅用于检测故障。 为了实际执行故障转移,需要将其中一名Sentinels选为故障转移的负责人,并有权继续进行操作。 这仅在大多数Sentinel进程的投票中才发生。

因此,例如,如果你有5个Sentinel进程,并且给定主节点的quorum 设置为2,则将发生以下情况:

  • 如果两个Sentinel同时同意主节点不可访问,则其中两个将尝试启动故障转移。
  • 如果总共至少有三个Sentinel可以访问,则故障转移将被授权并实际上开始。

实际上,这意味着在发生故障期间,如果大多数Sentinel进程无法进行对话(在少数分区中也没有故障转移),则Sentinel不会启动故障转移。

1.2.5.其他Sentinel选项

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

sentinel <option_name> <master_name> <option_value>

和用于以下目的:

  • down-after-milliseconds是指Sentinel开始认为实例已关闭的情况下实例不可到达的时间(以毫秒为单位)(不回复我们的PING或错误回复)。
  • parallel-syncs 设置在故障转移后可以重新配置为使用新的主节点的复制节点数。 数字越小,完成故障转移过程所花费的时间越多,但是,如果将复制节点配置为提供旧数据,则你可能不希望所有复制节点同时与主节点重新同步。 尽管复制过程在大多数情况下不会阻塞复制节点,但是有一段时间会停止从主节点加载批量数据。 通过将此选项设置为1,你可能想要确保一次只能访问一个复制节点。

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

所有配置参数都可以在运行时使用SENTINEL SET命令进行修改。 有关更多信息,请参见“在运行时重新配置Sentinel”部分。

1.2.6.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 |
+-------------------+

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

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

网络分区以斜线显示为间断行:

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

另请注意:

  • 主节点称为M1,M2,M3,...,Mn。
  • 复制节点称为R1,R2,R3,...,Rn(R代表复制节点)。
  • Sentinel被称为S1,S2,S3,...,Sn。
  • Client称为C1,C2,C3,...,Cn。
  • 当实例由于Sentinel动作而更改角色时,我们将其放在方括号中,因此[M1]表示由于Sentinel干预而成为主节点实例。

请注意,我们永远不会显示仅使用两个Sentinel的设置,因为Sentinels始终需要与majority(监控)进行交谈才能启动故障转移。

示例1:仅两个Sentinels,DON'T DO THIS

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

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

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

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

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

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

示例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一样与旧主节点位于同一分区中的客户端可能会继续向旧主节点写入数据。 此数据将永远丢失,因为当分区恢复正常时,主节点将被重新配置为新主节点的复制节点,从而丢弃其数据集。

使用以下Redis复制功能可以缓解此问题,如果主节点检测到不再能够将其写入转移到指定数量的副本,则该功能可以停止接受写入。

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

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

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

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

示例3:客户端盒子中的Sentinel

有时我们只有两个Redis盒子可用,一个用于主节点目录,一个用于复制节点。 在这种情况下,示例2中的配置不可行,因此我们可以采用以下方法,其中将Sentinels放置在客户端所在的位置:

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

      Configuration: quorum = 2

在此设置中,Sentinels的观点与客户端相同:如果大多数客户端可以访问主节点,则很好。 C1,C2,C3是通用客户端,并不意味着C1标识连接到Redis的单个客户端。 它更可能是诸如应用程序服务器,Rails应用程序之类的东西。

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

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

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

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

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

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

      Configuration: quorum = 3

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

从理论上讲,此设置可以删除运行C2和S4的框,并将quorum数设置为2。但是,如果我们的应用层中没有高可用性,我们不太可能希望Redis端拥有HA。

1.2.7.Sentinel,Docker,NAT和可能的问题

Docker使用一种称为端口映射的技术:与该程序认为正在使用的端口相比,在Docker容器内运行的程序可能会使用不同的端口公开。 为了在同一服务器上同时使用同一端口运行多个容器,这很有用。

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

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

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

由于Sentinels使用主节点 INFO输出信息自动检测复制,因此检测到的复制节点将无法访问,并且Sentinel将永远无法对主节点进行故障转移,因为从系统的角度来看,没有好的复制节点,因此目前没有用Sentinel监视一组使用Docker部署的主节点实例和复制节点实例,除非你指示Docker映射端口1:1

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

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

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

1.3.快速教程

在本文档的下一部分中,将逐步介绍有关Sentinel API,配置和语义的所有详细信息。 但是,对于想尽快使用系统ASAP的人来说,本节是一个教程,显示如何配置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。 它标识了主节点及其复制节点。 由于每个主节点集都有不同的名称,因此Sentinel可以同时监视不同的主节点集和复制节点集。
  • quorum设置为2(sentinel Monitor配置指令的最后一个参数)。
  • down-after-milliseconds值是5000毫秒,即5秒,因此,只要我们在此时间内没有收到来自ping的任何答复,主节点就会被检测为失败。

启动三个Sentinels后,你将看到它们记录的一些消息,例如:

+monitor master mymaster 127.0.0.1 6379 quorum 2

这是一个Sentinel事件,如果你使用SUBSCRIBE调用后面指定的事件名称,则可以通过Pub/Sub接收此类事件。

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

1.3.1.向Sentinel询问主节点状态

与Sentinel入门有关的最明显的事情是检查它监视的主节点是否运行良好:

$ 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"

如你所见,它会打印许多有关主节点的信息。 以下是我们特别感兴趣的一些:

  1. num-other-sentinels是2,所以我们知道Sentinel已经为该主节点检测到了另外两个Sentinel。 如果你查看日志,将会看到生成的+sentinel事件。
  2. flags只是master(主节点)。 如果主节点宕机,我们也可以在这里看到s_down 或o_down 标志。
  3. num-slaves正确设置为1,因此Sentinel还检测到我们的主节点有附加的复制节点。

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

SENTINEL replicas mymaster
SENTINEL sentinels mymaster

第一个将提供有关连接到主节点的复制节点的类似信息,第二个将提供有关其他Sentinel的信息。

1.3.2.获取当前主节点的地址

正如我们已经指定的,Sentinel还充当要连接到一组主节点和复制节点的客户端的配置提供程序。 由于可能的故障转移或重新配置,客户端不知道谁是给定实例集的当前活动主节点,因此Sentinel导出API来询问以下问题:

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

1.3.3.测试故障转移

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

redis-cli -p 6379 DEBUG sleep 30

这个命令将使我们的主节点不再可及,睡眠30秒。 出于某种原因,它基本上模拟了主节点悬挂。

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

  1. 每个Sentinel都通过+sdown事件检测到主节点已关闭。
  2. 此事件随后被升级为+odown,这意味着多个Sentinel同意主节点不可访问的事实。
  3. 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命令和内部信息。

1.4.Sentinel API

Sentinel提供了一个API,以便检查其状态,检查受监视的主节点和复制节点的运行状况,订阅以便接收特定的通知以及在运行时更改Sentinel配置。

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

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

1.4.1.Sentinel命令

从Redis 2.8开始,SENTINEL命令是Sentinel的主要API。 以下是其子命令的列表(在适用的地方注明了最低版本):

  • SENTINEL CKQUORUM <master name> 检查当前的Sentinel配置是否能够达到故障转移主节点所需的仲裁(quorum)数,以及授权故障转移所需的(获胜的)票数。在监视系统中应使用此命令来检查Sentinel部署是否正常。
  • SENTINEL FLUSHCONFIG 强制Sentinel重写其在磁盘上的配置,包括当前Sentinel状态。 通常,每当状态变化时(在重新启动后一直保留在磁盘上的状态子集的上下文中),Sentinel都会重写配置。 但是,有时由于操作错误,磁盘故障,程序包升级脚本或配置管理器,配置文件可能会丢失。 在这种情况下,强制Sentinel重写配置文件的方法很方便。 即使先前的配置文件完全丢失,此命令也有效。
  • SENTINEL FAILOVER <master name> 强制进行故障转移,就好像主节点不可访问一样,并且无需征得其他Sentinels的同意(但是将发布新版本的配置,以便其他Sentinels可以更新其配置)。
  • SENTINEL GET-MASTER-ADDR-BY-NAME <master name> 返回具有该名称的主节点的ip和端口号。 如果此主节点正在进行故障转移或成功终止,它将返回升级复制节点的地址和端口。
  • SENTINEL INFO-CACHE (>= 3.2) 从主节点和复制节点返回缓存的INFO输出。
  • SENTINEL IS-MASTER-DOWN-BY-ADDR 从当前Sentinel的角度检查ip:port指定的主节点是否处于关闭状态。 此命令主要供内部使用。
  • SENTINEL MASTER <master name> 显示指定主节点的状态和信息。
  • SENTINEL MASTERS 显示受监视的主节点及其状态的列表。
  • SENTINEL MONITOR 启动Sentinel的监视。 有关更多信息,请参考“在运行时重新配置Sentinel''部分。
  • SENTINEL MYID (>= 6.2) 返回Sentinel实例的ID。
  • SENTINEL PENDING-SCRIPTS 此命令返回有关挂起脚本的信息。
  • SENTINEL REMOVE 停止Sentinel的监视。 有关更多信息,请参考”在运行时重新配置Sentinel''部分。
  • SENTINEL REPLICAS <master name> (>= 5.0) 显示此主节点的复制节点及其状态。
  • SENTINEL SENTINELS <master name>显示此主节点的sentinel实例及其状态的列表。
  • SENTINEL SET 设置Sentinel的监视配置。 有关更多信息,请参考“在运行时重新配置Sentinel''部分。
  • SENTINEL SIMULATE-FAILURE (crash-after-election|crash-after-promotion|help) (>= 3.2) 此命令模拟不同的Sentinel崩溃方案。
  • SENTINEL RESET <pattern> 此命令将重置所有具有匹配名称的主节点。 pattern参数是glob样式的模式。 重置过程将清除主节点中的所有先前状态(包括正在进行的故障转移),并删除已发现并与主节点关联的每个复制节点和标记。

为了进行连接管理和管理,Sentinel支持以下Redis命令子集:

  • ACL (>= 6.2) 此命令管理Sentinel访问控制列表。 有关更多信息,请参阅ACL文档页面和Sentinel访问控制列表身份验证
  • AUTH (>= 5.0.1) 验证客户端连接。 有关更多信息,请参阅AUTH命令和使用身份验证配置Sentinel实例
  • CLIENT 此命令管理客户端连接。 有关更多信息,请参见其子命令页面。
  • COMMAND (>= 6.2) 该命令返回有关命令的信息。 有关更多信息,请参考COMMAND命令及其各种子命令。
  • HELLO (>= 6.0) 切换连接的协议。 有关更多信息,请参考HELLO 命令。
  • INFO 返回有关Sentinel服务器的信息和统计信息。 有关更多信息,请参见INFO 命令。
  • PING 该命令仅返回PONG。
  • ROLE 此命令返回字符串“sentinel”和受监视的主节点列表。 有关更多信息,请参考ROLE命令。
  • SHUTDOWN 关闭Sentinel实例。

最后,Sentinel还支持SUBSCRIBEUNSUBSCRIBEPSUBSCRIBEPUNSUBSCRIBE命令。 有关更多详细信息,请参见发布/订阅消息部分。

1.4.2.在运行时重新配置Sentinel

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

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

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

 

以下是SENTINEL SET命令的示例,用于修改称为objects-cache的主节点的down-after-milliseconds配置:

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

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

SENTINEL SET objects-cache-master quorum 5

请注意,由于SENTINEL MASTER以简单的解析格式(作为field/value对数组)提供了所有配置参数,因此没有等效的GET命令。

1.4.3.添加或删除哨兵(Sentinels)

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

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

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

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

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

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

1.4.4.删除旧的主节点或无法访问的复制节点

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

此外,在故障转移之后,将故障转移的主节点虚拟地添加为新主节点的复制节点,这样,一旦重新可用,它将被重新配置为与新主节点一起复制。

但是,有时你想从Sentinel监视的复制节点列表中永久删除一个复制节点(可能是旧的主节点)。

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

1.4.5.发布/订阅(Pub/Sub)消息

客户端可以将Sentinel用作与Redis兼容的发布/订阅服务器(但不能使用PUBLISH),以便SUBSCRIBEPSUBSCRIBE 到频道并获得有关特定事件的通知。

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

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

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

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

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

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

  • +reset-master <instance details> -- 主节点被重置。
  • +slave <instance details> -- 检测到并附加了新复制节点。
  • +failover-state-reconf-slaves <instance details> -- 故障转移状态已更改为"reconf-slaves''状态。
  • +failover-detected <instance details> -- 检测到由另一个Sentinel或任何其他外部实体启动的故障转移(已将附加复制节点变成了主节点)。
  • +slave-reconf-sent <instance details> -- 领导者哨兵(sentinel )向该实例发送了REPLICAOF命令,以便为新复制节点重新配置它。
  • +slave-reconf-inprog <instance details> -- 重新配置的复制节点显示为新的主节点ip:port对的复制节点,但是同步过程尚未完成。
  • +slave-reconf-done <instance details> -- 复制节点已与新的主节点及时同步。
  • -dup-sentinel <instance details> -- 已删除指定主节点的一个或多个sentinel(例如,在重新启动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)状态。
  • +new-epoch <instance details> -- 当前时代已更新。
  • +try-failover <instance details> -- 新的故障转移正在进行中,正等待多数选出。
  • +elected-leader <instance details> -- 赢得指定时期的选举,可以进行故障转移。
  • +failover-state-select-slave <instance details> -- 我们正在尝试寻找合适的复制节点进行升级。
  • 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模式已退出

1.4.6.处理-BUSY状态

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

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

1.4.7.复制节点(Replicas)优先级

Redis实例具有一个称为复制节点优先级(replica-priority)的配置参数。 该信息由Redis复制节点实例在其INFO 输出中公开,Sentinel使用该信息以便从可用于故障转移主节点的复制节点中选择一个复制节点:

  1. 如果复制节点优先级设置为0,则永远不会将复制节点提升为主节点。
  2. Sentinel优先选择优先级较低的复制节点。

例如,如果当前主节点的同一数据中心中有一个复制节点S1,而另一个数据中心中有另一个复制节点S2,则可以将优先级S10设置为S1,将优先级S100设置为S2。 主节点失败,并且S1和S2均可用,S1将是首选。

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

1.4.8.Sentinel和Redis身份验证

当将主节点配置为要求客户端进行身份验证时,作为一种安全措施,复制节点也需要知道凭据,以便与主节点进行身份验证并创建用于异步复制协议的主节点连接。

1.4.9.Redis访问控制列表认证

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

为了使Sentinels在配置有ACL时连接到Redis服务器实例,Sentinel配置必须包含以下指令:

sentinel auth-user <master-group-name> <username>
sentinel auth-pass <master-group-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 在主节点上, 为了设置身份验证密码,并确保实例将不处理对未经身份验证的客户端的请求。
  • masterauth 在复制节点上, 为了使复制节点能够与主节点进行身份验证,以便从中正确复制数据。

使用Sentinel时,没有单个主节点,因为在故障转移之后,复制节点可能会充当主节点,并且可以重新配置旧的主节点以充当复制节点,因此你要做的是将上述指令设置为你所有的实例,包括主节点实例和复制节点实例。

这通常也是明智的设置,因为你不想只在主节点中保护数据,而在复制节点数据库中可以访问相同的数据。

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

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

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

1.4.10.使用身份验证配置Sentinel实例

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

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

1.4.11.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的超级用户和密码(例如,上例中的admin和admin-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客户端的文档。

1.4.12.Sentinel仅密码身份验证

要将Sentinel与仅口令身份验证一起使用,请按如下所示将requirepass配置指令添加到所有Sentinel实例:

requirepass "your_password_here"

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

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

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

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

1.4.13.Sentinel客户实现

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

1.5.更高级的概念

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

1.5.1.DOWN和DOWN故障状态

Redis Sentinel具有关闭的两个不同概念,一个称为主观关闭(Subjectively Down)条件(SDOWN),并且是给定Sentinel实例本地的关闭条件。 另一个称为客观关闭(Objectively Down)状态(ODOWN),当足够多的Sentinels(至少是配置为受监视主节点的仲裁(quorum )参数的数量)具有SDOWN条件并使用SENTINEL is-master-down-by-addr命令,从其他Sentinels获得反馈。

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

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

  • PING 回复 +PONG.
  • PING 回复 -LOADING error.
  • PING 回复 -MASTERDOWN error.

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

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

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

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

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

ODOWN条件仅适用于主节点。 对于其他类型的实例,Sentinel不需要执行操作,因此复制节点和其他sentinel永远不会达到ODOWN状态,而只有SDOWN可以达到。

但是,SDOWN也具有语义含义。 例如,处于SDOWN状态的复制节点未选择通过执行故障转移的Sentinel进行升级。

1.5.2.Sentinel和复制节点(replicas )自动发现

Sentinels与其他Sentinels保持联系,以便相互检查彼此的可用性并交换消息。 但是,你无需在运行的每个Sentinel实例中都配置其他Sentinel地址的列表,因为Sentinel使用Redis实例的发布/订阅( Pub/Sub)功能来发现正在监视相同主节点和复制节点的其他Sentinels。

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

同样,你无需配置附加到主节点的复制节点列表,因为Sentinel会通过查询Redis自动发现此列表。

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

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

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

  • 主节点声明的复制节点(根据当前配置)将配置为复制节点(作为当前主节点的复制节点)。
  • 连接到错误主节点的复制节点将被重新配置为使用正确的主节点的复制节点。

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

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

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

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

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

1.5.4.复制节点选择和优先级

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

复制节点选择过程评估有关复制节点的以下信息:

  • 与主节点的断开时间。
  • 复制节点优先级。
  • 复制偏移已处理。
  • 运行ID。

发现复制节点与主节点断开连接的时间超过已配置主节点超时的十倍(down-after-milliseconds选项),以及从进行故障转移的Sentinel角度来看,主节点不可用的时间, 被认为不适合故障转移,因此被跳过。

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

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

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

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

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

如果有强烈推荐的机器,则Redis主节点(在故障转移后可能会变成复制节点)和复制节点都必须配置有复制节点优先级。 否则,所有实例都可以使用默认的运行ID运行(这是建议的设置,因为通过复制偏移量选择复制节点更加有趣)。

可以将Redis实例配置为特殊的复制节点优先级(replica-priority)零,以便Sentinels永远不会将其选择为新的主节点实例。 但是,以这种方式配置的复制节点仍将由Sentinels重新配置,以便在故障转移后与新的主节点进行复制,唯一的区别是它永远不会成为主节点。

1.6.算法和内部

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

1.6.1.Quorum(仲裁数)

前面的部分显示了Sentinel监视的每个主节点都与Quorum配置的相关联。 它指定需要就主节点的不可达性或错误情况达成一致的Sentinel进程数,以触发故障转移。

然而,在触发故障转移之后,为了使故障转移实际执行,至少大多数Sentinel必须授权Sentinel进行故障转移。 Sentinel绝不会在少数Sentinels存在的分区中执行故障转移。

让我们尝试使事情变得更加清晰:

  • Quorum: Sentinel进程数,需要检测错误条件才能将主节点标记为ODOWN。
  • 故障转移由ODOWN状态触发。
  • 触发故障转移后,要求尝试进行故障转移的Sentinel要求获得大多数Sentinels的授权(如果将Quorum设置为大于多数的数目,则需要获得更多的授权)。

差异看似微妙,但实际上很容易理解和使用。 例如,如果你有5个Sentinel实例,并且Quorum设置为2,则一旦2个Sentinels认为主节点无法访问,就会触发故障转移,但是,只有两个哨兵至少获得3个哨兵的授权,它才能进行故障转移。

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

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

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

1.6.2.配置时代(epochs)

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

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

此外,Sentinels有一条规则:如果一个Sentinel投票给另一个Sentinel以进行给定主节点的故障转移,它将等待一段时间尝试再次对同一主节点进行故障转移。 此延迟是你可以在sentinel.conf中配置的故障转移超时(failover-timeout)。 这意味着Sentinels将不会在同一时间尝试对同一主节点进行故障转移,第一个要求获得授权的主节点将尝试,如果失败,另一个将在一段时间后尝试,依此类推。

Redis Sentinel保证了活动属性,即如果大多数Sentinel能够讲话,则在主节点掉线时最终将被授权进行故障转移。

Redis Sentinel还保证了安全属性,即每个Sentinel都将使用不同的配置时代对同一主节点进行故障转移。

1.6.3.配置传播(propagation)

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

为了使故障转移成功,它要求Sentinel能够将REPLICAOF NO ONE命令发送到所选复制节点 ,并且稍后在主节点的INFO输出中观察到切换到主节点的情况。

此时,即使复制节点的重新配置正在进行中,故障切换也被认为是成功的,并且所有Sentinel都必须开始报告新配置。

传播新配置的方式是为什么我们需要为每个Sentinel故障转移都授予不同版本号(配置时代)的原因。

每个Sentinel都使用Redis Pub/Sub消息在主节点和所有复制节点中连续广播其主节点配置版本。 同时,所有哨兵都等待消息以查看其他Sentinels所通告的配置是什么。

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

因为每个配置都有不同的版本号,所以较大的版本总是胜过较小的版本。

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

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

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

1.6.4.分区下的一致性

Redis Sentinel配置最终是一致的,因此每个分区都将收敛到可用的更高配置。 但是,在使用Sentinel的真实系统中,存在三种不同的播放器:

  • Redis 实例.
  • Sentinel 实例.
  • Clients.

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

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

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

在此系统中,原始状态是Redis 3是主节点,而Redis 1和2是复制节点。 发生分区,从而隔离了旧主节点。 Sentinels 1和2开始了故障转移,将Sentinel 1提升为新的主节点。

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

我们知道,当网络分区修复后,Sentinel 3将更新其配置,但是,如果有客户端与旧的主节点分区,则在分区期间会发生什么?

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

根据你的配置,你是否希望发生这种情况:

  • 如果你将Redis用作缓存,则即使客户端B的数据丢失,它仍然可以方便地写入旧的Master。
  • 如果你将Redis用作存储,那不好,你需要配置系统以部分防止此问题。

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

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

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

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

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

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

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

1.6.5.Sentinel持久化状态

Sentinel 状态保留在Sentinel 配置文件中。 例如,每次为主节点接收或创建新配置(leader Sentinels)时,该配置就会与配置时代一起保存在磁盘上。 这意味着可以安全地停止和重新启动Sentinel进程。

1.6.6.TILT模式

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

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

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

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

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

  • 它根本不起作用。
  • 由于不再信任检测故障的能力,因此它开始对SENTINEL is-master-down-by-addr请求作出否定回复。

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

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

有关此手册页中使用的复制节点(slave)一词的注释:从Redis 5开始,如果不是为了向后兼容,则Redis项目将不再使用slave一词。 不幸的是,在该命令中,“slave”一词是协议的一部分,因此,只有当该API自然被弃用时,才能删除这种情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值