ASKING

自 3.0.0 起可用。

时间复杂度: O(1)

当集群客户端收到-ASK重定向时,会向目标节点发送ASKING命令,然后是重定向的命令。这通常由集群客户端自动完成。

如果-ASK在交易过程中收到重定向,只需向目标节点发送一条 ASKING 命令,即可将完整的交易发送到目标节点。

有关详细信息,请参阅Redis 集群规范中的 ASK 重定向。

返回值

简单的字符串回复:OK。

CLUSTER ADDSLOTS slot [slot ...]

自 3.0.0 起可用。

时间复杂度: O(N),其中 N 是哈希槽参数的总数

此命令对于修改节点的集群配置视图很有用。具体来说,它将一组哈希槽分配给接收命令的节点。如果命令成功,节点会将指定的哈希槽映射到自己,并开始广播新的配置。

但请注意:

  • 仅当从接收命令的节点的角度来看,所有指定的插槽当前未分配时,该命令才有效。一个节点将拒绝获得已经属于某个其他节点(包括它自己)的插槽的所有权。
  • 如果多次指定同一个插槽,则该命令将失败。
  • 作为命令执行的副作用,如果指定为参数的槽中的一个槽设置为importing,则一旦节点将(以前未绑定的)槽分配给自身,此状态就会被清除。

例子

例如,以下命令将插槽 1 2 3 分配给接收命令的节点:

> CLUSTER ADDSLOTS 1 2 3
OK

但是尝试再次执行它会导致错误,因为已经分配了插槽:

> CLUSTER ADDSLOTS 1 2 3
ERR Slot 1 is already busy

Redis 集群中的使用

此命令仅在集群模式下有效,在以下 Redis 集群操作中很有用:

  • 为了创建一个新的集群,ADDSLOTS 用于初始设置主节点,在它们之间拆分可用的哈希槽。
  • 为了修复未分配某些插槽的损坏集群。

有关插槽传播和警告的信息

请注意,一旦节点为自己分配了一组槽,它将开始在心跳包头中传播此信息。然而,其他节点只有在它们的槽尚未与另一个节点绑定时才会接受该信息,或者如果发布新哈希槽的节点的配置纪元大于表中当前列出的节点。

这意味着只有编排 Redis 集群的应用程序(如 )才应谨慎使用此命令,redis-cli如果在正确的上下文之外使用该命令,可能会使集群处于错误状态或导致数据丢失。

返回值

简单字符串回复:OK如果命令成功。否则返回错误。

CLUSTER ADDSLOTSRANGE start-slot end-slot [start-slot end-slot ...]

自 7.0.0 起可用。

时间复杂度: O(N),其中 N 是起始槽和结束槽参数之间的槽总数。

CLUSTER ADDSLOTSRANGE类似于CLUSTER ADDSLOTS命令,因为它们都将哈希槽分配给节点。

这两个命令之间的区别在于,ADDSLOTS将插槽列表分配给节点,而ADDSLOTSRANGE将插槽范围列表(由开始和结束插槽指定)分配给节点。

例子

要将 slot 1 2 3 4 5 分配给节点,ADDSLOTS命令是:

> CLUSTER ADDSLOTS 1 2 3 4 5
OK

可以使用以下ADDSLOTSRANGE命令完成相同的操作:

> CLUSTER ADDSLOTSRANGE 1 5
OK

Redis 集群中的使用

此命令仅在集群模式下有效,在以下 Redis 集群操作中很有用:

  • 为了创建一个新的集群,使用 ADDSLOTSRANGE 来初始设置主节点,在它们之间拆分可用的哈希槽。
  • 为了修复未分配某些插槽的损坏集群。

返回值

简单字符串回复:OK如果命令成功。否则返回错误。

CLUSTER BUMPEPOCH

自 3.0.0 起可用。

时间复杂度: O(1)

推进集群配置纪元。

CLUSTER BUMPEPOCH命令从连接的节点触发集群配置纪元的增量。如果节点的 config epoch 为零,或者它小于集群的最大 epoch,则 epoch 将递增。

注意: config epoch 管理由集群内部执行,依赖于节点的共识。CLUSTER BUMPEPOCH尝试在未获得共识的情况下增加配置 epoch ,因此使用它可能会违反“最后一次故障转移获胜”规则。谨慎使用。

返回值

简单字符串回复:BUMPED如果 epoch 增加了,或者STILL节点已经拥有集群中最大的 config epoch。

CLUSTER COUNT-FAILURE-REPORTS node-id

自 3.0.0 起可用。

时间复杂度: O(N) 其中 N 是失败报告的数量

该命令返回指定节点的故障报告数。故障报告是 Redis 集群用来提升 PFAIL状态的方式,即节点不可访问,升级为FAIL状态,即集群中的大多数主节点在一个时间窗口内同意节点不可访问。

更多细节:

  • PFAIL当节点无法访问的时间大于配置的节点 timeout时,节点会标记另一个节点,这是 Redis 集群的基本配置参数。
  • 状态中的节点在PFAIL心跳包的 gossip 部分中提供。
  • 每次节点处理来自其他节点的 gossip 数据包时,它都会创建(并在需要时刷新 TTL)故障报告,并记住给定节点表示另一个给定节点处于PFAIL状态。
  • 每个故障报告的生存时间是节点超时时间的两倍。
  • 如果在给定时间一个节点有另一个节点标记PFAIL为到,并广播一条消息,强制所有可以到达的节点将节点标记为。PFAILFAILFAIL

此命令返回当前未过期的当前节点的故障报告数(因此在节点超时时间的两倍内收到)。该计数不包括我们询问该计数的节点对我们作为参数传递的节点 ID 的看法,该计数仅包括该节点从其他节点收到的故障报告。

此命令主要用于调试,当 Redis Cluster 的故障检测器未按我们认为的那样运行时。

返回值

整数回复:节点的活动故障报告数。

CLUSTER COUNTKEYSINSLOT slot

自 3.0.0 起可用。

时间复杂度: O(1)

返回指定 Redis Cluster 哈希槽中的键数。该命令仅查询本地数据集,因此联系不服务于指定哈希槽的节点将始终导致返回计数为零。

> CLUSTER COUNTKEYSINSLOT 7000
(integer) 50341

返回值

整数回复:指定哈希槽中的键数,如果哈希槽无效,则返回错误。

CLUSTER DELSLOTS slot [slot ...]

自 3.0.0 起可用。

时间复杂度: O(N),其中 N 是哈希槽参数的总数

在 Redis 集群中,每个节点都会跟踪哪个主节点正在为特定的哈希槽提供服务。

CLUSTER DELSLOTS命令要求特定的 Redis 集群节点忘记哪个主节点正在为指定为参数的哈希槽提供服务。

在收到CLUSTER DELSLOTS命令并因此删除了传递的哈希槽的关联的节点的上下文中,我们说这些哈希槽是未绑定的。请注意,当一个节点没有被配置为处理它们(可以使用 CLUSTER ADDSLOTS命令完成)并且如果它没有收到有关谁拥有这些哈希槽的任何信息(它可以从心跳或更新消息中学习)。

如果一个具有未绑定哈希槽的节点从另一个节点接收到一个声称是其中一些哈希槽所有者的心跳包,则立即建立关联。此外,如果接收到的心跳或更新消息的配置时期大于节点自己的,则重新建立关联。

但是,请注意:

  • 该命令仅在所有指定的插槽都已与某个节点关联时才有效。
  • 如果多次指定同一个插槽,则该命令将失败。
  • 作为命令执行的副作用,节点可能会进入 关闭状态,因为并非所有哈希槽都被覆盖。

例子

以下命令从接收命令的节点中删除插槽 5000 和 5001 的关联:

> CLUSTER DELSLOTS 5000 5001
OK

Redis 集群中的使用

此命令仅在集群模式下有效,可能对调试有用,并且可以在创建新集群时手动编排集群配置。它目前不被 使用redis-cli,主要是为了 API 的完整性而存在。

返回值

简单字符串回复:OK如果命令成功。否则返回错误。

CLUSTER DELSLOTSRANGE start-slot end-slot [start-slot end-slot ...]

自 7.0.0 起可用。

时间复杂度: O(N),其中 N 是起始槽和结束槽参数之间的槽总数。

CLUSTER DELSLOTSRANGE命令类似于CLUSTER DELSLOTS命令,因为它们都从节点中删除哈希槽。不同之处在于CLUSTER DELSLOTS需要一个哈希槽列表以从节点中删除,而CLUSTER DELSLOTSRANGE需要一个槽范围列表(由开始和结束槽指定)从节点中删除。

例子

要从节点中删除槽 1 2 3 4 5,CLUSTER DELSLOTS命令是:

> CLUSTER DELSLOTS 1 2 3 4 5
OK

可以使用以下CLUSTER DELSLOTSRANGE命令完成相同的操作:

> CLUSTER DELSLOTSRANGE 1 5
OK

但是,请注意:

  • 该命令仅在所有指定的插槽都已与该节点关联时才有效。
  • 如果多次指定同一个插槽,则该命令将失败。
  • 作为命令执行的副作用,节点可能会进入关闭状态,因为并非所有哈希槽都被覆盖。

Redis 集群中的使用

此命令仅在集群模式下有效,可能对调试有用,并且可以在创建新集群时手动编排集群配置。它目前不被 使用redis-cli,主要是为了 API 的完整性而存在。

返回值

简单字符串回复:OK如果命令成功。否则返回错误。

CLUSTER FAILOVER [FORCE|TAKEOVER]

自 3.0.0 起可用。

时间复杂度: O(1)

此命令只能发送到 Redis 集群副本节点,强制副本启动其主实例的手动故障转移。

手动故障转移是一种特殊类型的故障转移,通常在没有实际故障时执行,但我们希望以安全的方式将当前主服务器与其一个副本(即我们发送命令的节点)交换,没有任何数据丢失窗口。它的工作方式如下:

  1. 副本告诉主服务器停止处理来自客户端的查询。
  2. 主服务器使用当前复制偏移量回复副本。
  3. 副本等待复制偏移量在其一侧匹配,以确保它在继续之前处理了来自主服务器的所有数据。
  4. 副本启动故障转移,从大多数主节点获取新的配置纪元,并广播新配置。
  5. 旧主人收到配置更新:解除对其客户端的阻止并开始回复重定向消息,以便他们继续与新主人聊天。

通过这种方式,客户端会自动从旧主服务器转移到新主服务器,并且只有在变成新主服务器的副本已经处理了来自旧主服务器的所有复制流时。

自 3.0.0 起可用。

时间复杂度: O(1)

此命令只能发送到 Redis 集群副本节点,强制副本启动其主实例的手动故障转移。

手动故障转移是一种特殊类型的故障转移,通常在没有实际故障时执行,但我们希望以安全的方式将当前主服务器与其一个副本(即我们发送命令的节点)交换,没有任何数据丢失窗口。它的工作方式如下:

副本告诉主服务器停止处理来自客户端的查询。
主服务器使用当前复制偏移量回复副本。
副本等待复制偏移量在其一侧匹配,以确保它在继续之前处理了来自主服务器的所有数据。
副本启动故障转移,从大多数主节点获取新的配置纪元,并广播新配置。
旧主人收到配置更新:解除对其客户端的阻止并开始回复重定向消息,以便他们继续与新主人聊天。
通过这种方式,客户端会自动从旧主服务器转移到新主服务器,并且只有在变成新主服务器的副本已经处理了来自旧主服务器的所有复制流时。

FORCE 选项:当主服务器关闭时手动故障转移

命令行为可以通过两个选项进行修改:FORCE和TAKEOVER。

如果给出了FORCE选项,则副本不会与主节点执行任何握手,这可能无法访问,而是从第 4 点开始尽快启动故障转移。当我们想要在主节点启动手动故障转移时,这很有用不再可达。

然而,使用FORCE,我们仍然需要大多数 master 可用,以便授权故障转移并为将成为 master 的副本生成新的配置 epoch。

TAKEOVER 选项:没有集群共识的手动故障转移

在某些情况下,这还不够,我们希望副本在不与集群的其余部分达成任何协议的情况下进行故障转移。一个现实世界的用例是将不同数据中心中的副本大规模提升为主节点,以执行数据中心切换,同时所有主节点都关闭或分区。

TAKEOVER选项暗示了FORCE暗示的一切,但也不使用任何集群授权来进行故障转移。副本接收 CLUSTER FAILOVER TAKEOVER将改为:

  1. 单方面生成一个新的configEpoch,只取当前可用的最大 epoch,如果它的本地配置 epoch 还不是最大的,则增加它。
  2. 为自己分配其主节点的所有哈希槽,并将新配置传播到尽快可达的每个节点,并最终传播到每个其他节点。

请注意,TAKEOVER 违反了Redis Cluster 的 last-failover-wins 原则,因为副本生成的配置纪元在几个方面违反了配置纪元的正常生成:

  1. 不能保证它实际上是更高的配置时期,因为例如,我们可以在少数人中使用TAKEOVER选项,也不会执行任何消息交换来生成新的配置时期。
  2. 如果我们生成一个碰巧与另一个实例发生冲突的配置纪元,最终我们的配置纪元,或者与我们相同纪元的另一个实例,将使用配置纪元冲突解决算法被移走。

因此,应谨慎使用TAKEOVER选项。

实施细节和注意事项

  • 除非指定了TAKEOVER选项,否则CLUSTER FAILOVER不会同步执行故障转移。它只安排手动故障转移,绕过故障检测阶段。
  • OK回复并不能保证故障转移会成功。
  • 只有当集群中的大多数主节点都将副本称为副本时,才能将副本提升为主节点。如果副本是刚刚添加到集群中的新节点(例如在升级之后),集群中的所有主节点可能还不知道它。要检查主节点是否知道新副本,您可以向每个主节点发送CLUSTER NODES或CLUSTER REPLICAS并检查它是否显示为副本,然后再将CLUSTER FAILOVER发送到副本。
  • 要检查故障转移是否实际发生,您可以使用ROLE(INFO REPLICATION在成功故障转移后指示“role:master”)或CLUSTER NODES来验证集群的状态在命令发送后的某个时间发生了变化。
  • 要检查故障转移是否失败,请检查副本的日志中是否存在“手动故障转移超时”,如果副本在几秒钟后放弃,则会记录该日志。

返回值

简单字符串回复:OK如果命令被接受并且将尝试手动故障转移。如果操作无法执行,例如我们正在与一个已经是主节点的节点交谈,则会出现错误。

CLUSTER FLUSHSLOTS

自 3.0.0 起可用。

时间复杂度: O(1)

从节点中删除所有插槽。

CLUSTER FLUSHSLOTS从连接的节点中删除所有关于槽的信息。只能在数据库为空时调用。

返回值

简单的字符串回复:OK

CLUSTER FORGET node-id

自 3.0.0 起可用。

时间复杂度: O(1)

该命令用于从接收该命令的 Redis Cluster 节点的已知节点集中删除通过其节点 ID 指定的节点。换句话说,指定的节点从接收命令的节点的节点表中删除。

因为当给定节点是集群的一部分时,参与集群的所有其他节点都知道它,为了将节点从集群中完全删除,必须向所有剩余节点发送CLUSTER FORGET命令,无论事实上他们是主人或复制品。

但是该命令不能简单地从接收命令的节点的内部节点表中删除该节点,它还实现了一个禁止列表,不允许再次添加相同的节点作为处理 心跳数据包的八卦部分的副作用从其他节点接收。

为什么需要禁止名单的详细信息

在下面的示例中,我们将展示为什么该命令不仅必须从节点表中删除给定节点,而且还要防止它在一段时间内再次重新插入。

假设我们有四个节点,A、B、C 和 D。为了结束只有三个节点的集群 A、B、C,我们可以按照以下步骤操作:

  1. 将 D 中的所有哈希槽重新分片到节点 A、B、C。
  2. D 现在为空,但仍列在 A、B 和 C 的节点表中。
  3. 我们联系 A,然后发送CLUSTER FORGET D.
  4. B 向节点 A 发送一个心跳包,其中列出了节点 D。
  5. A 不再知道节点 D(参见步骤 3),因此它开始与 D 握手。
  6. D端重新添加到A的节点表中。

如您所见,以这种方式删除节点是脆弱的,我们需要尽快向所有节点发送 CLUSTER FORGET命令,希望在此期间没有闲话部分正在处理。由于这个问题,该命令实现了一个禁止列表,每个条目都有一个过期时间。

所以这个命令真正做的是:

  1. 指定的节点将从节点表中删除。
  2. 被删除节点的节点 ID 被添加到禁止列表中,持续 1 分钟。
  3. 该节点在处理从其他节点收到的心跳包中的八卦部分时,将跳过禁止列表中列出的所有节点ID。

这样,我们就有 60 秒的时间来通知集群中的所有节点我们要删除一个节点。

不允许执行命令的特殊条件

该命令在以下情况下不成功并返回错误:

  1. 在节点表中找不到指定的节点 ID。
  2. 接收命令的节点是副本,指定的节点 ID 标识其当前的主节点。
  3. 节点 ID 标识我们向其发送命令的同一节点。

返回值

简单字符串回复:OK如果命令执行成功,否则返回错误。

CLUSTER GETKEYSINSLOT slot count

自 3.0.0 起可用。

时间复杂度: O(log(N)) 其中 N 是请求键的数量

该命令返回存储在联系节点中的键名数组并散列到指定的散列槽。要返回的最大密钥数通过count参数指定,以便此 API 的用户可以批量处理密钥。

此命令的主要用途是在集群插槽从一个节点到另一个节点的重新散列期间。执行重新散列的方式在 Redis 集群规范中公开,或者以更简单的形式公开,作为CLUSTER SETSLOT命令文档的附录。

> CLUSTER GETKEYSINSLOT 7000 3
1) "key_39015"
2) "key_89793"
3) "key_92937"

返回值

数组回复:从 0 开始计算Redis 数组回复中的键名。

CLUSTER INFO

自 3.0.0 起可用。

时间复杂度: O(1)

CLUSTER INFO提供有关 Redis Cluster 重要参数的INFO样式信息。以下是示例输出,然后是报告的每个字段的描述。

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:1483972
cluster_stats_messages_received:1483968
total_cluster_links_buffer_limit_exceeded:0
  • cluster_state:状态是ok节点是否能够接收查询。fail如果至少有一个哈希槽是未绑定的(没有关联的节点),处于错误状态(为其服务的节点被标记为 FAIL 标志),或者如果该节点无法访问大多数主节点。
  • cluster_slots_assigned:与某个节点关联的槽数(未绑定)。这个数字应该是 16384 节点才能正常工作,这意味着每个哈希槽都应该映射到一个节点。
  • cluster_slots_ok:映射到不在FAIL或PFAIL状态的节点的哈希槽数。
  • cluster_slots_pfail:映射到PFAIL状态节点的哈希槽数。请注意,只要故障检测算法PFAIL不提升状态,这些哈希槽仍然可以正常工作。仅表示我们目前无法与节点对话,但可能只是暂时性错误。FAILPFAIL
  • cluster_slots_fail:映射到FAIL状态节点的哈希槽数。如果此数字不为零,则节点无法提供查询,除非在配置cluster-require-full-coverage中设置为no。
  • cluster_known_nodes:集群中已知节点的总数,包括HANDSHAKE当前可能不是集群正确成员的状态的节点。
  • cluster_size:服务于集群中至少一个哈希槽的主节点的数量。
  • cluster_current_epoch: 局部Current Epoch变量。这用于在故障转移期间创建唯一递增的版本号。
  • cluster_my_epoch:Config Epoch我们正在与之交谈的节点的。这是分配给该节点的当前配置版本。
  • cluster_stats_messages_sent:通过集群节点到节点二进制总线发送的消息数。
  • cluster_stats_messages_received:通过集群节点到节点二进制总线接收到的消息数。
  • total_cluster_links_buffer_limit_exceeded:由于超出cluster-link-sendbuf-limit配置而释放的集群链接的累积计数。

Redis 集群规范文档中提供了有关 Current Epoch 和 Config Epoch 变量的更多信息。

返回值

批量字符串回复:命名字段和值之间的映射,以:由两个字节组成的换行符分隔的行的形式CRLF。

CLUSTER KEYSLOT key

自 3.0.0 起可用。

时间复杂度: O(N) 其中 N 是密钥中的字节数

返回一个整数,标识指定键散列到的散列槽。该命令主要用于调试和测试,因为它通过 API 公开了哈希算法的底层 Redis 实现。此命令的示例用例:

  1. 客户端库可以使用 Redis 来测试自己的哈希算法,生成随机密钥并使用本地实现和使用 Redis CLUSTER KEYSLOT命令对它们进行哈希处理,然后检查结果是否相同。
  2. 人类可以使用这个命令来检查什么是哈希槽,然后是相关的 Redis 集群节点,负责给定的键。

例子

> CLUSTER KEYSLOT somekey
(integer) 11058
> CLUSTER KEYSLOT foo{hash_tag}
(integer) 2515
> CLUSTER KEYSLOT bar{hash_tag}
(integer) 2515

请注意,该命令实现了完整的散列算法,包括对散列标签的支持,这是 Redis Cluster 键散列算法的特殊属性,散列只是在键名之间{以及}如果在键名中找到这样的模式,以强制多个键由同一个节点处理。

返回值

整数回复:哈希槽号。

CLUSTER LINKS

自 7.0.0 起可用。

时间复杂度: O(N) 其中 N 是集群节点的总数

Redis 集群中的每个节点都与集群中的每个对等点维护一对长寿命 TCP 链接:一个用于向对等点发送出站消息,一个用于从对等点接收入站消息。

CLUSTER LINKS将所有此类对等链接的信息输出为一个数组,其中每个数组元素是一个映射,其中包含单个链接的属性及其值。

例子

以下是示例输出:

> CLUSTER LINKS
1)  1) "direction"
    2) "to"
    3) "node"
    4) "8149d745fa551e40764fecaf7cab9dbdf6b659ae"
    5) "create-time"
    6) (integer) 1639442739375
    7) "events"
    8) "rw"
    9) "send-buffer-allocated"
   10) (integer) 4512
   11) "send-buffer-used"
   12) (integer) 0
2)  1) "direction"
    2) "from"
    3) "node"
    4) "8149d745fa551e40764fecaf7cab9dbdf6b659ae"
    5) "create-time"
    6) (integer) 1639442739411
    7) "events"
    8) "r"
    9) "send-buffer-allocated"
   10) (integer) 0
   11) "send-buffer-used"
   12) (integer) 0

每个映射由相应集群链路的以下属性及其值组成:

  1. direction:此链接由本地节点topeer建立,或由本地节点frompeer接受。
  2. node: 对等节点的节点 ID。
  3. create-time:链接的创建时间。(在to链路的情况下,这是本地节点创建 TCP 链路的时间,而不是实际建立的时间。)
  4. events:当前为链接注册的事件。r表示可读事件,w表示可写事件。
  5. send-buffer-allocated: 链接发送缓冲区的分配大小,用于缓冲向对等方传出的消息。
  6. send-buffer-used:当前保存数据(消息)的链接发送缓冲区部分的大小。

返回值

数组回复:一个地图数组,其中每个地图包含集群链接的各种属性及其值。

CLUSTER MEET ip port

自 3.0.0 起可用。

时间复杂度: O(1)

CLUSTER MEET用于将启用了集群支持的不同 Redis 节点连接到一个工作集群中。

基本思想是默认情况下节点不相互信任,并且被认为是未知的,因此不同的集群节点不太可能因为系统管理错误或网络地址修改而混合成一个。

因此,为了让一个给定的节点接受另一个节点到组成 Redis 集群的节点列表中,只有两种方法:

  1. 系统管理员发送一个CLUSTER MEET命令来强制一个节点与另一个节点会面。
  2. 一个已知节点会在 gossip 部分发送一个我们不知道的节点列表。如果接收节点信任发送节点为已知节点,它将处理 gossip 部分并向仍然未知的节点发送握手。

请注意,Redis Cluster 需要形成全网格(每个节点都与其他节点相连),但为了创建集群,无需发送形成全网格所需的所有CLUSTER MEET命令。重要的是发送足够多的CLUSTER MEET消息,以便每个节点可以通过一系列已知节点到达其他节点。由于心跳包中八卦信息的交换,丢失的链接将被创建。

因此,如果我们通过CLUSTER MEET将节点 A 与节点 B 链接,并将 B 与 C 链接,A 和 C 将找到它们握手并创建链接的方法。

另一个例子:如果我们想象一个由以下四个节点组成的集群,称为 A、B、C 和 D,我们可以只向 A 发送以下命令集:

  1. CLUSTER MEET B-ip B-port
  2. CLUSTER MEET C-ip C-port
  3. CLUSTER MEET D-ip D-port

作为所有其他节点知道并被所有其他节点知道的副作用A,它将在心跳包中发送八卦部分,这将允许其他节点创建彼此的链接,在几秒钟内形成一个完整的网格,甚至如果集群很大。

此外, CLUSTER MEET不需要是互惠的。如果我将命令发送给 A 以加入 B,我不需要将命令也发送给 B 以加入 A。

实现细节:MEET 和 PING 数据包

当给定节点收到CLUSTER MEET消息时,命令中指定的节点仍然不知道我们将命令发送到的节点。因此,为了让节点强制接收方接受它作为受信任节点,它会发送一个 MEET数据包而不是PING数据包。这两个数据包具有完全相同的格式,但前者迫使接收者确认节点为受信任的。

返回值

简单字符串回复:OK如果命令成功。如果指定的地址或端口无效,则返回错误。

CLUSTER MYID

自 3.0.0 起可用。

时间复杂度: O(1)

返回节点的 ID。

CLUSTER MYID命令返回与连接的集群节点关联的唯一、自动生成的标识符。

返回值

批量字符串回复:节点 ID。

CLUSTER NODES

自 3.0.0 起可用。

时间复杂度: O(N) 其中 N 是集群节点的总数

Redis 集群中的每个节点都有当前集群配置的视图,由一组已知节点、我们与这些节点的连接状态、它们的标志、属性和分配的插槽等给出。

CLUSTER NODES以序列化格式提供所有这些信息,即我们正在联系的节点的当前集群配置,该序列化格式恰好与 Redis 集群本身使用的完全相同,以便将集群状态存储在磁盘上(但是磁盘上的集群状态在末尾附加了一些附加信息)。

请注意,通常愿意获取集群哈希槽和节点地址之间映射的客户端应该使用CLUSTER SLOTS。 提供更多信息的集群节点应该用于管理任务、调试和配置检查。它也用于redis-cli管理集群。

序列化格式

该命令的输出只是一个以空格分隔的 CSV 字符串,其中每一行代表集群中的一个节点。以下是输出示例:

07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002 master - 0 1426238316232 2 connected 5461-10922
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003 master - 0 1426238318243 3 connected 10923-16383
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006 slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001 myself,master - 0 0 1 connected 0-5460

每行由以下字段组成:

<id> <ip:port@cport> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>

每个字段的含义如下:

  1. id: 节点 ID,一个 40 个字符的随机字符串,在创建节点时生成并且永远不会再次更改(除非CLUSTER RESET HARD使用)。
  2. ip:port@cport:客户端应联系节点以运行查询的节点地址。
  3. flags: 逗号分隔的标志列表:myself, master, slave, fail?, fail, handshake, noaddr, nofailover, noflags. 标志将在下一节中详细解释。
  4. master:如果节点是副本,并且master已知,则为master节点ID,否则为“-”字符。
  5. ping-sent:发送当前活动 ping 的毫秒 unix 时间,如果没有挂起的 ping,则为零。
  6. pong-recv: 最后一次收到 pong 的毫秒 unix 时间。
  7. config-epoch:当前节点(如果节点是副本,则为当前主节点)的配置时期(或版本)。每次发生故障转移时,都会创建一个新的、唯一的、单调递增的配置时期。如果多个节点声称提供相同的哈希槽,则具有更高配置时期的节点获胜。
  8. link-state:用于节点到节点集群总线的链路状态。我们使用此链接与节点进行通信。可以是connected或disconnected。
  9. slot:哈希槽号或范围。从参数号 9 开始,但总共可能有多达 16384 个条目(从未达到限制)。这是此节点服务的哈希槽列表。如果条目只是一个数字,则按此方式解析。如果是范围,则格式为start-end,表示该节点负责从start到的所有哈希槽,end包括开始值和结束值。

标志的含义(字段编号 3):

  • myself:您正在联系的节点。
  • master: 节点是主人。
  • slave: 节点是一个副本。
  • fail?: 节点处于PFAIL状态。您正在联系的节点无法访问,但在逻辑上仍可访问(未处于FAIL状态)。
  • fail: 节点处于FAIL状态。PFAIL将状态提升为 的多个节点无法访问FAIL。
  • handshake: 不受信任的节点,我们正在握手。
  • noaddr: 此节点没有已知地址。
  • nofailover:副本不会尝试故障转移。
  • noflags: 根本没有标志。

已发布配置时期的注意事项

副本广播它们的主配置时期(以便在UPDATE 发现它们过时时获得消息),因此副本的真实配置时期(这或多或少毫无意义,因为它们不提供哈希槽)只能是获得检查标记为 的节点myself,这是我们要求生成CLUSTER NODES输出的节点的条目。其他副本纪元反映了它们在心跳包中发布的内容,即它们当前正在复制的主节点的配置纪元。

特殊插槽条目

通常,与给定节点关联的哈希槽采用以下格式之一,如上文所述:

  1. 单号:3894
  2. 范围:3900-4000

然而,节点哈希槽可以处于特殊状态,用于在节点重启后(AOF/RDB 文件中的键与节点哈希槽配置不匹配)或正在进行重新分片操作时传达错误. 这两个状态是导入和迁移。

Redis 规范中解释了这两种状态的含义,但是两种状态的要点如下:

  • 导入槽还不是节点哈希槽的一部分,正在进行迁移。仅当使用该ASK命令时,节点才会接受有关这些槽的查询。
  • 迁移槽已分配给节点,但正在迁移到其他某个节点。如果命令中的所有键都已存在,该节点将接受查询,否则它将发出所谓的ASK 重定向,以强制直接在导入节点中创建新键。

导入和迁移槽在CLUSTER NODES输出中发出,如下所示:

  • 导入槽: [slot_number-<-importing_from_node_id]
  • 迁移槽: [slot_number->-migrating_to_node_id]

以下是一些导入和迁移槽的示例:

  • [93-<-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f]
  • [1002-<-67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1]
  • [77->-e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca]
  • [16311->-292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f]

请注意,该格式没有任何空格,因此CLUSTER NODES输出格式是纯 CSV,即使发出此特殊插槽也是以空格作为分隔符。但是,格式的完整解析器应该能够处理它们。

注意:

  1. 迁移和导入槽仅添加到标记为 的节点myself。该信息对于节点来说是本地的,对于它自己的槽来说。
  2. 导入和迁移插槽作为附加信息提供。如果节点分配了一个给定的哈希槽,它也将是哈希槽列表中的一个普通数字,因此不知道哈希槽迁移的客户端可以跳过这个特殊字段。

返回值

批量字符串回复:序列化集群配置。

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

CLUSTER REPLICAS node-id

从 5.0.0 开始可用。

时间复杂度: O(1)

该命令提供从指定主节点复制的副本节点列表。该列表以CLUSTER NODES使用的相同格式提供(有关格式规范,请参阅其文档)。

如果指定节点未知,或者根据接收命令的节点的节点表,该节点不是主节点,则该命令将失败。

请注意,如果从给定的主节点添加、移动或删除副本,并且我们向尚未收到配置更新的节点询问CLUSTER REPLICAS ,它可能会显示陈旧信息。然而最终(如果没有网络分区,则在几秒钟内)所有节点将就与给定主节点关联的节点集达成一致。

返回值

该命令以与CLUSTER NODES相同的格式返回数据。

CLUSTER REPLICATE node-id

自 3.0.0 起可用。

时间复杂度: O(1)

该命令将节点重新配置为指定主节点的副本。如果接收命令的节点是空的 master,作为命令的副作用,节点角色会从 master 更改为 replica。

一旦一个节点变成另一个主节点的副本,就不需要通知其他集群节点这个变化:节点之间交换的心跳包会自动传播新的配置。

副本将始终接受该命令,假设:

  1. 指定的节点 ID 存在于其节点表中。
  2. 指定的节点 ID 无法识别我们将命令发送到的实例。
  3. 指定的节点 ID 是主节点。

如果接收到命令的节点已经不是replica,而是master,只有满足以下附加条件,命令才会成功,节点才会转为replica:

  1. 该节点不提供任何哈希槽。
  2. 该节点为空,密钥空间中根本没有存储任何密钥。

如果命令成功,新副本将立即尝试联系其主服务器以便从中进行复制。

返回值

简单字符串回复:OK如果命令执行成功,否则返回错误。

CLUSTER RESET [HARD|SOFT]

自 3.0.0 起可用。

时间复杂度: O(N),其中 N 是已知节点的数量。该命令可能会执行 FLUSHALL 作为副作用。

重置 Redis 集群节点,根据重置类型或多或少的剧烈方式,可以是hard或soft。请注意, 如果主节点持有一个或多个密钥,则此命令不适用于主节点,在这种情况下,必须首先删除主节点密钥,例如先使用FLUSHALL,然后再使用CLUSTER RESET。

对节点的影响:

  1. 集群中的所有其他节点都被遗忘。
  2. 所有分配/打开的插槽都被重置,因此插槽到节点的映射被完全清除。
  3. 如果节点是副本,则它将变成(空)主节点。它的数据集被刷新,所以最后节点将是一个空的主节点。
  4. 仅硬重置:生成新的节点 ID。
  5. 仅硬重置:currentEpoch并且configEpochvars 设置为 0。
  6. 新配置保存在磁盘上的节点集群配置文件中。

此命令主要用于重新配置 Redis 集群节点,以便在新的不同集群的上下文中使用。Redis 集群测试框架也广泛使用该命令,以便在每次执行新的测试单元时重置集群的状态。

如果未指定重置类型,则默认为soft。

返回值

简单字符串回复:OK如果命令成功。否则返回错误。

CLUSTER SAVECONFIG

自 3.0.0 起可用。

时间复杂度: O(1)

强制节点将nodes.conf配置保存在磁盘上。在返回命令调用之前,fsync(2)以确保配置已刷新到计算机磁盘上。

该命令主要用于nodes.conf节点状态文件由于某种原因丢失/删除的情况,我们想从头开始重新生成它。在通过CLUSTER命令对节点集群配置进行普通更改的情况下,它也很有用,以确保新配置持久保存在磁盘上,但是所有命令通常应该能够自动调度以将配置持久保存在磁盘上。这样做对于重启时系统的正确性很重要。

返回值

简单字符串回复:OK如果操作失败,则返回错误。

CLUSTER SET-CONFIG-EPOCH config-epoch

自 3.0.0 起可用。

时间复杂度: O(1)

此命令在新节点中设置特定的配置时期。它仅在以下情况下有效:

  1. 节点的节点表为空。
  2. 节点当前配置纪元为零。

这些先决条件是必需的,因为通常手动更改节点的配置纪元是不安全的,我们希望确保具有较高配置纪元值的节点(即最后一个故障转移)在声明哈希槽时胜过其他节点所有权。

但是,此规则有一个例外,即从头开始创建新集群时。Redis Cluster config epoch 冲突解决算法可以处理启动时所有配置相同配置的新节点,但是这个过程很慢,应该是例外,只是为了确保无论发生什么,最后两个节点总是远离状态具有相同的配置时期。

因此,使用CLUSTER SET-CONFIG-EPOCH,当创建一个新集群时,我们可以在加入集群之前为每个节点分配一个不同的渐进配置时期。

返回值

简单字符串回复:OK如果命令执行成功,否则返回错误。

CLUSTER SETSLOT slot IMPORTING node-id|MIGRATING node-id|NODE node-id|STABLE

自 3.0.0 起可用。

时间复杂度: O(1)

CLUSTER SETSLOT负责以不同的方式改变接收节点中哈希槽的状态。根据使用的子命令,它可以:

  1. MIGRATING子命令:设置一个处于迁移状态的哈希槽。
  2. IMPORTING子命令:设置一个处于导入状态的哈希槽。
  3. STABLE子命令:从哈希槽清除任何导入/迁移状态。
  4. NODE子命令:将哈希槽绑定到不同的节点。

该命令及其子命令集对于启动和结束集群实时重新分片操作很有用,这些操作是通过在源节点中将哈希槽设置为迁移状态并在目标节点中导入状态来完成的。

下面记录了每个子命令。最后,您将找到有关如何使用此命令和其他相关命令执行实时重新分片的说明。

集群集槽迁移

此子命令将槽设置为迁移状态。为了将槽设置为该状态,接收命令的节点必须是哈希槽的所有者,否则返回错误。

当插槽设置为迁移状态时,节点以下列方式更改行为:

  1. 如果收到有关现有密钥的命令,则按通常方式处理该命令。
  2. 如果收到有关不存在的键的命令,ASK则节点会发出重定向,要求客户端仅重试该特定查询到destination-node. 在这种情况下,客户端不应将其哈希槽更新为节点映射。
  3. 如果命令包含多个键,如果不存在,则行为与第 2 点相同,如果全部存在,则与第 1 点相同,但如果仅存在部分键,则命令TRYAGAIN按顺序发出错误以便将感兴趣的键完成迁移到目标节点,以便执行多键命令。

集群集插槽导入

此子命令与 的相反MIGRATING,并准备目标节点从指定的源节点导入密钥。该命令仅在节点还不是指定哈希槽的所有者时才有效。

当插槽设置为导入状态时,节点以下列方式更改行为:

  1. 关于这个哈希槽的命令被拒绝并像MOVED往常一样生成重定向,但在命令跟在ASKING命令之后的情况下,在这种情况下执行命令。

这样,当处于迁移状态的节点产生ASK重定向时,客户端会联系目标节点,发送ASKING,然后立即发送命令。这样,关于旧节点中不存在的键或已迁移到目标节点的键的命令将在目标节点中执行,以便:

  1. 新密钥总是在目标节点中创建。在哈希槽迁移期间,我们只需要移动旧键,而不是新键。
  2. 有关已迁移键的命令在作为迁移目标的节点(新的哈希槽所有者)的上下文中正确处理,以保证一致性。
  3. 如果不询问,行为与通常情况相同。这保证了哈希槽映射损坏的客户端不会在目标节点中写入错误,从而创建尚未迁移的密钥的新版本。

集群集时隙稳定

这个子命令只是从插槽中清除迁移/导入状态。它主要用于修复被卡在错误状态的集群redis-cli --cluster fix。通常,这两种状态会在迁移结束时使用SETSLOT ... NODE ...子命令自动清除,如下一节所述。

集群 SETSLOT节点

NODE子命令是语义最复杂的命令。它将哈希槽与指定节点相关联,但是该命令仅在特定情况下有效,并且根据槽状态具有不同的副作用。以下是该命令的一组前置条件和副作用:

  1. 如果当前哈希槽的所有者是接收命令的节点,但是为了命令的效果,槽将被分配给不同的节点,如果在接收命令的节点中仍然存在该哈希槽的键,则该命令将返回错误.
  2. 如果插槽处于迁移状态,则在将插槽分配给另一个节点时清除状态。
  3. 如果槽在接收命令的节点中处于导入状态,并且命令将槽分配给该节点(这发生在目标节点中,在哈希槽从一个节点重新分片到另一个节点结束时),该命令具有以下副作用: A)导入状态被清除。B) 如果节点 config epoch 还不是集群中最大的,它会生成一个新节点并将新的 config epoch 分配给自己。这样,它的新哈希槽所有权将胜过由先前故障转移或槽迁移创建的任何过去配置。

需要注意的是,第 3 步是唯一一次 Redis 集群节点会在没有其他节点同意的情况下创建新的 config epoch。这只发生在手动配置操作时。然而,这不可能创建一个非瞬态设置,其中两个节点具有相同的配置纪元,因为 Redis 集群使用配置纪元冲突解决算法。

返回值

简单字符串回复:OK如果命令成功,则返回所有子命令。否则返回错误。

Redis Cluster live resharding解释

CLUSTER SETSLOT命令是 Redis Cluster 用来将一个哈希槽中包含的所有键从一个节点迁移到另一个节点的重要部分。这就是在其他命令的帮助下协调迁移的方式。我们将拥有哈希槽当前所有权的节点称为source节点,以及我们想要迁移节点的destination节点。

  1. 使用将目标节点槽设置为导入状态CLUSTER SETSLOT IMPORTING
  2. 使用将源节点槽设置为迁移状态CLUSTER SETSLOT MIGRATING
  3. 使用CLUSTER GETKEYSINSLOT命令从源节点获取密钥,并使用MIGRATE命令将它们移动到目标节点。
  4. 发送CLUSTER SETSLOT NODE 到目的节点。
  5. 发送CLUSTER SETSLOT NODE 到源节点。
  6. 发送CLUSTER SETSLOT NODE 到其他主节点(可选)。

笔记:

  • 第 1 步和第 2 步的顺序很重要。当源节点配置为重定向时,我们希望目标节点准备好接受ASK重定向。
  • 第 4 步和第 5 步的顺序很重要。目标节点负责将更改传播到集群的其余部分。如果源节点在目标节点之前被通知并且目标节点在它被设置为新的槽所有者之前崩溃,那么即使在成功的故障转移之后,槽也没有所有者。
  • 第 6 步,发送SETSLOT到未参与重新分片的节点,在技术上不是必需的,因为配置最终会自行传播。但是,这样做是一个好主意,以便尽快阻止节点指向错误的节点以使哈希槽移动,从而减少重定向以找到正确的节点。

CLUSTER SLAVES node-id

自 3.0.0 起可用。

时间复杂度: O(1)

弃用通知: 从 Redis 版本 5.0.0 开始,此命令被视为已弃用。虽然它不太可能被完全删除,但更喜欢使用 CLUSTER REPLICAS 代替它。

关于本手册页中使用的单词 slave 和命令名称的说明:从 Redis 版本 5 开始,如果不是为了向后兼容,Redis 项目不再使用单词 slave。请使用新命令CLUSTER REPLICAS。命令CLUSTER SLAVES将继续为向后兼容工作。

该命令提供从指定主节点复制的副本节点列表。该列表以CLUSTER NODES使用的相同格式提供(有关格式规范,请参阅其文档)。

如果指定节点未知,或者根据接收命令的节点的节点表,该节点不是主节点,则该命令将失败。

请注意,如果从给定的主节点添加、移动或删除副本,并且我们向尚未收到配置更新的节点询问CLUSTER SLAVES ,它可能会显示陈旧信息。然而最终(如果没有网络分区,则在几秒钟内)所有节点将就与给定主节点关联的节点集达成一致。

返回值

该命令以与CLUSTER NODES相同的格式返回数据。

CLUSTER SLOTS

自 3.0.0 起可用。

时间复杂度: O(N) 其中 N 是集群节点的总数

CLUSTER SLOTS返回有关哪些集群槽映射到哪些 Redis 实例的详细信息。该命令适用于 Redis 集群客户端库实现,以检索(或在收到重定向时更新)将集群哈希槽与实际节点网络信息相关联的映射,以便在收到命令时发送到命令中指定的键的正确实例。

每个节点的网络信息是一个包含以下元素的数组:

  • 首选端点(IP 地址、主机名或 NULL)
  • 端口号
  • 节点 ID
  • 附加网络元数据的地图

首选端点和端口一起定义了客户端应该用来发送给定槽的请求的位置。端点的 NULL 值表示节点有一个未知的端点,客户端应该连接到它用来发送CLUSTER SLOTS命令但使用从命令返回的端口的同一端点。当 Redis 节点位于 Redis 不知道其端点的负载均衡器后面时,此未知端点配置很有用。哪个端点设置为首选由cluster-preferred-endpoint-type配置确定。

额外的网络元数据作为每个节点的第四个参数的映射提供。可能会返回以下网络元数据:

  • IP:当首选端点未设置为 IP 时。
  • 主机名:当节点具有已宣布的主机名但主端点未设置为主机名时。

嵌套结果数组
每个嵌套结果是:

  • 起始槽位范围
  • 结束插槽范围
  • 表示为嵌套网络信息的插槽范围的主控
  • 插槽范围的第一个主副本
  • 第二个副本
  • ...继续,直到返回此 master 的所有副本。

每个结果都包括列出的插槽范围内的主实例的所有活动副本。不返回失败的副本。

第三个嵌套回复保证是主实例在插槽范围内的网络信息。第三个嵌套回复之后的所有网络信息都是主服务器的副本。

如果集群实例有非连续槽(例如 1-400,900,1800-6000),那么每个顶级槽范围回复的主副本和副本网络信息结果将被复制。

返回值

数组回复:带有网络信息的插槽范围的嵌套列表。

例子

> CLUSTER SLOTS
1) 1) (integer) 0
   2) (integer) 5460
   3) 1) "127.0.0.1"
      2) (integer) 30001
      3) "09dbe9720cda62f7865eabc5fd8857c5d2678366"
      4) 1) hostname
         2) "host-1.redis.example.com"
   4) 1) "127.0.0.1"
      2) (integer) 30004
      3) "821d8ca00d7ccf931ed3ffc7e3db0599d2271abf"
      4) 1) hostname
         2) "host-2.redis.example.com"
2) 1) (integer) 5461
   2) (integer) 10922
   3) 1) "127.0.0.1"
      2) (integer) 30002
      3) "c9d93d9f2c0c524ff34cc11838c2003d8c29e013"
      4) 1) hostname
         2) "host-3.redis.example.com"
   4) 1) "127.0.0.1"
      2) (integer) 30005
      3) "faadb3eb99009de4ab72ad6b6ed87634c7ee410f"
      4) 1) hostname
         2) "host-4.redis.example.com"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 30003
      3) "044ec91f325b7595e76dbcb18cc688b6a5b434a1"
      4) 1) hostname
         2) "host-5.redis.example.com"
   4) 1) "127.0.0.1"
      2) (integer) 30006
      3) "58e6e48d41228013e5d9c1c37c5060693925e97e"
      4) 1) hostname
         2) "host-6.redis.example.com"

**警告:**在未来的版本中,可能会有更多元素更好地描述节点。一般来说,客户端实现应该只依赖于某些参数位于指定的固定位置这一事实,但可能会跟随更多参数并且应该被忽略。同样,如果可能,客户端库应该尝试处理旧版本可能只有主端点和端口参数的事实。

历史

  • Redis 版本 >= 4.0.0:添加了节点 ID。
  • Redis 版本 >= 7.0.0:添加了额外的网络元数据并添加了对主机名和未知端点的支持。

READONLY

自 3.0.0 起可用。

时间复杂度: O(1)

为与 Redis 集群副本节点的连接启用读取查询。

通常,副本节点会将客户端重定向到给定命令中涉及的哈希槽的权威主节点,但是客户端可以使用副本来使用READONLY命令扩展读取。

READONLY告诉 Redis Cluster 副本节点,客户端愿意读取可能陈旧的数据,并且对运行写入查询不感兴趣。

当连接处于只读模式时,只有当操作涉及副本的主节点不提供服务的键时,集群才会向客户端发送重定向。这可能是因为:

  1. 客户端发送了一个关于此副本的主服务器从未服务过的哈希槽的命令。
  2. 集群被重新配置(例如重新分片)并且副本不再能够为给定的哈希槽提供命令。

返回值

简单的字符串回复

READWRITE

自 3.0.0 起可用。

时间复杂度: O(1)

禁用连接到 Redis 集群副本节点的读取查询。

默认情况下禁用针对 Redis 集群副本节点的读取查询,但您可以使用READONLY命令在每个连接的基础上更改此行为。READWRITE命令将连接的只读模式标志重置回读写。

返回值

简单的字符串回复