CLUSTER FORGET

用法
CLUSTER FORGET node-id
复杂度
O(1)
3.0.0
ACL 类别
@admin, @dangerous, @slow

此命令用于将通过其节点 ID 指定的节点从接收命令的 Valkey 集群节点的*已知节点*集合中移除。换句话说,指定的节点将从接收命令的节点的*节点表*中移除。

因为当给定节点是集群的一部分时,集群中所有其他参与节点都会知道它。为了将一个节点从集群中完全移除,必须将 CLUSTER FORGET 命令发送给所有剩余节点,无论它们是主节点还是副本节点。

然而,该命令不能简单地从接收命令的节点的内部节点表中删除该节点,它还实现了一个禁止列表,防止同一节点因处理从其他节点接收到的心跳包的*gossip 部分*而被再次添加。

禁止列表的必要性详情

在以下示例中,我们将展示为什么该命令不仅需要从节点表中移除给定节点,还需要在一段时间内阻止其被重新插入。

假设我们有四个节点: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 命令,希望在此期间没有 gossip 部分正在处理。由于这个问题,该命令实现了一个禁止列表,其中每个条目都有一个过期时间。

所以该命令真正做的是:

  1. 指定节点将从节点表中移除。
  2. 被移除节点的节点 ID 将被添加到禁止列表,有效期为 1 分钟。
  3. 当处理从其他节点接收到的心跳包中的 gossip 部分时,该节点将跳过禁止列表中列出的所有节点 ID。

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

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

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

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

RESP2/RESP3 回复

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