Sentinel 客户端规范

如何为 Redis Sentinel 构建客户端

Redis Sentinel 是一个针对 Redis 实例的监控解决方案,它处理 Redis 主服务器的自动故障转移和服务发现(对于给定的一组实例,谁是当前的主服务器?)。由于 Sentinel 既负责在故障转移期间重新配置实例,又为连接到 Redis 主服务器或副本的客户端提供配置,因此客户端需要明确支持 Redis Sentinel。

本文档面向希望在客户端实现中支持 Sentinel 的 Redis 客户端开发人员,目标如下

  • 通过 Sentinel 自动配置客户端。
  • 提高 Redis Sentinel 自动故障转移的安全性。

有关 Redis Sentinel 工作原理的详细信息,请查看 Redis 文档,因为本文档仅包含 Redis 客户端开发人员所需的信息,并且期望读者熟悉 Redis Sentinel 的工作原理。

通过 Sentinel 进行 Redis 服务发现

Redis Sentinel 使用“stats”或“cache”等名称标识每个主服务器。每个名称实际上标识一个实例组,由一个主服务器和数量可变的副本组成。

用于网络内特定目的的 Redis 主服务器的地址可能会在自动故障转移、手动触发的故障转移(例如为了升级 Redis 实例)和其他原因发生后发生更改。

通常,Redis 客户端具有一些硬编码配置,指定网络内 Redis 主服务器实例的地址,如 IP 地址和端口号。但是,如果主服务器地址发生更改,则需要对每个客户端进行人工干预。

支持 Sentinel 的 Redis 客户端可以使用 Redis Sentinel 根据主服务器名称自动发现 Redis 主服务器的地址。因此,支持 Sentinel 的客户端应能够选择性地将硬编码的 IP 地址和端口替换为以下输入

  • 指向已知 Sentinel 实例的 ip:port 对列表。
  • 服务名称,如“cache”或“timelines”。

这是客户端应遵循的步骤,以便从 Sentinel 列表和服务名称获取主服务器地址。

步骤 1:连接到第一个 Sentinel

客户端应迭代 Sentinel 地址列表。对于每个地址,它都应尝试使用短超时(数百毫秒量级)连接到 Sentinel。如果出现错误或超时,则应尝试下一个 Sentinel 地址。

如果尝试所有 Sentinel 地址均未成功,则应向客户端返回错误。

第一个响应客户端请求的 Sentinel 应放在列表的开头,以便在下一次重新连接时,我们首先尝试在上次连接尝试中可访问的 Sentinel,从而最大程度地减少延迟。

步骤 2:询问主服务器地址

一旦与 Sentinel 建立连接,客户端应重试在 Sentinel 上执行以下命令

SENTINEL get-master-addr-by-name master-name

其中,master-name 应替换为用户指定的实际服务名称。

此调用的结果可能是以下两种回复之一

  • ip:port 对。
  • 空回复。这意味着 Sentinel 不知道此主服务器。

如果收到 ip:port 对,则应使用此地址连接到 Redis 主服务器。否则,如果收到空回复,则客户端应尝试列表中的下一个 Sentinel。

步骤 3:在目标实例中调用 ROLE 命令

一旦客户端发现主实例的地址,它应尝试与主服务器建立连接,并调用 ROLE 命令,以便验证实例的角色实际上是主服务器。

如果 ROLE 命令不可用(它在 Redis 2.8.12 中引入),则客户端可以求助于 INFO replication 命令,解析输出的 role: 字段。

如果实例不是预期的主服务器,则客户端应等待一小段时间(几百毫秒),并应从步骤 1 重新开始尝试。

处理重新连接

一旦服务名称解析为主地址并与 Redis 主实例建立连接,则每次需要重新连接时,客户端都应使用 Sentinel 从步骤 1 重新开始解析地址。例如,Sentinel 应在以下情况下再次联系

  • 如果客户端在超时或套接字错误后重新连接。
  • 如果客户端重新连接,因为它被用户明确关闭或重新连接。

在上述情况下以及客户端与 Redis 服务器断开连接的任何其他情况下,客户端都应重新解析主地址。

Sentinel 故障转移断开连接

从 Redis 2.8.12 开始,当 Redis Sentinel 更改实例的配置时,例如将副本提升为主服务器,在故障转移后将主服务器降级为复制到新主服务器,或仅仅更改过时副本实例的主服务器地址时,它会向实例发送 CLIENT KILL type normal 命令,以确保所有客户端都断开与已重新配置实例的连接。这将强制客户端重新解析主地址。

如果客户端将联系尚未更新信息的 Sentinel,则通过 ROLE 命令验证 Redis 实例角色将失败,允许客户端检测到所联系的 Sentinel 提供了过时信息,并将重试。

注意:过时的主服务器可能在客户端联系过时的 Sentinel 实例时同时重新联机,因此客户端可能连接到过时的主服务器,但 ROLE 输出仍将匹配。但是,当主服务器再次返回时,Sentinel 将尝试将其降级为副本,从而触发新的断开连接。同样的道理也适用于连接到将重新配置为使用不同的主服务器进行复制的过时副本。

连接副本

有时,客户端有兴趣连接到副本,例如为了扩展读取请求。此协议通过略微修改步骤 2 来支持连接到副本。客户端应调用以下命令,而不是调用

SENTINEL get-master-addr-by-name master-name

客户端应改为调用

SENTINEL replicas master-name

以检索副本实例列表。

对称地,客户端应使用 ROLE 命令验证实例实际上是副本,以避免使用主服务器扩展读取查询。

连接池

对于实现连接池的客户端,在重新连接单个连接时,应再次联系 Sentinel,并且在主地址更改的情况下,应关闭所有现有连接并连接到新地址。

错误报告

在发生错误的情况下,客户端应正确地将信息返回给用户。具体来说

  • 如果无法联系到任何 Sentinel(因此客户端永远无法获得对 SENTINEL get-master-addr-by-name 的答复),则应返回一个明确指出 Redis Sentinel 无法访问的错误。
  • 如果池中的所有 Sentinel 都以 null 答复答复,则应使用 Sentinels 不知道此主服务器名称的错误通知用户。

Sentinel 列表自动刷新

或者,一旦收到对 get-master-addr-by-name 的成功答复,客户端可以按照以下过程更新其 Sentinel 节点内部列表

  • 使用命令 SENTINEL sentinels <master-name> 获取此主服务器的其他 Sentinel 列表。
  • 在列表末尾添加列表中尚未存在的每个 ip:port 对。

客户端不必能够通过更新其自己的配置来使列表持久化。升级 Sentinel 列表的内存中表示的能力已经可以用来提高可靠性。

订阅 Sentinel 事件以提高响应能力

Sentinel 文档 展示了客户端如何使用 Pub/Sub 连接到 Sentinel 实例,以便订阅 Redis 实例配置中的更改。

此机制可用于加速客户端的重新配置,也就是说,客户端可以监听 Pub/Sub 以便在配置发生更改时了解情况,以便运行本文档中说明的三步协议来解析新的 Redis 主机(或副本)地址。

但是,通过 Pub/Sub 接收的更新消息不应替代上述过程,因为无法保证客户端能够接收所有更新消息。

其他信息

有关其他信息或讨论本指南的具体方面,请向 Redis Google Group 发送消息。

为本页评分