CLUSTER FORGET
CLUSTER FORGET node-id
- 可用版本
- Redis 开源版 3.0.0
- 时间复杂度
- O(1)
- ACL 类别
-
@admin
,@slow
,@dangerous
,
此命令用于从接收命令的 Redis 集群节点的*已知节点*集合中移除一个通过其节点 ID 指定的节点。换句话说,指定的节点将从接收命令的节点的*节点表*中移除。
因为当一个给定节点是集群的一部分时,参与集群的所有其他节点都会知道它,因此为了将一个节点完全从集群中移除,必须将 CLUSTER FORGET
命令发送给所有剩余节点,无论它们是主节点还是副本节点。
然而,该命令不能简单地从接收命令的节点的内部节点表中删除该节点,它还实现了一个禁止列表,以防止由于处理从其他节点接收到的心跳包的*流言部分*而导致同一节点被再次添加。
从 Redis 7.2.0 开始,禁止列表包含在集群流言 ping/pong 消息中。这意味着 CLUSTER FORGET
命令不需要发送给集群中的所有节点。您可以在一个或多个节点上运行此命令,之后在大多数情况下它会传播到其他节点。
关于为什么需要禁止列表的详细信息
在以下示例中,我们将说明为什么该命令不仅要从节点表中移除给定节点,还要防止它在一段时间内被再次插入。
假设我们有四个节点 A、B、C 和 D。为了最终只剩下一个包含 A、B、C 三个节点的集群,我们可以按照以下步骤操作
- 将所有哈希槽从 D 重新分片到节点 A、B、C。
- D 现在是空的,但仍列在 A、B 和 C 的节点表中。
- 我们联系 A,并发送
CLUSTER FORGET D
。 - B 向节点 A 发送一个心跳包,其中列出了节点 D。
- A 不再知道节点 D(参见步骤 3),因此它与 D 启动握手。
- D 最终被重新添加到 A 的节点表中。
正如您所见,以这种方式移除节点是很脆弱的,我们需要尽快将 CLUSTER FORGET
命令发送给所有节点,希望在此期间没有流言部分正在处理。由于这个问题,该命令实现了一个禁止列表,其中每个条目都有一个过期时间。
因此,该命令实际执行的操作是
- 指定的节点将从节点表中移除。
- 被移除节点的节点 ID 将被添加到禁止列表,有效期为 1 分钟。
- 节点在处理从其他节点接收到的心跳包中的流言部分时,会跳过禁止列表中列出的所有节点 ID。
通过这种方式,我们有 60 秒的时间窗口通知集群中的所有节点我们要移除一个节点。
不允许执行命令的特殊条件
在以下情况下,命令不会成功并返回错误
- 在节点表中找不到指定的节点 ID。
- 接收命令的节点是一个副本节点,并且指定的节点 ID 是其当前主节点的 ID。
- 节点 ID 是我们发送命令的目标节点本身的 ID。
行为变更历史
>= 7.2.0
:自动将节点删除传播到集群中的其他节点,在大多数情况下允许通过一次调用删除节点。
RESP2/RESP3 回复
简单字符串回复:如果命令执行成功,则返回OK
。否则返回错误。历史
- 从 Redis 7.2.0 版本开始:被遗忘的节点通过流言自动在集群中传播。