翻译文章,原文地址:https://redis.io/commands/cluster-forget/
Available since 3.0.0.
Time complexity: O(1)
3.0.0版本后可用
时间复杂度:O(1)
The command is used in order to remove a node, specified via its node ID, from the set of known nodes of the Redis Cluster node receiving the command. In other words the specified node is removed from the nodes table of the node receiving the command.
该命令用于在redis集群节点接收到该命令后从集群已知的节点集合中移除掉给定节点id的节点。换句话说,接收到命令的节点的节点表中会移除掉指定节点。
Because when a given node is part of the cluster, all the other nodes participating in the cluster knows about it, in order for a node to be completely removed from a cluster, the CLUSTER FORGET command must be sent to all the remaining nodes, regardless of the fact they are masters or replicas.
因为指定节点是集群的一部分,集群中的所有其他节点都能感知到它,为了从集群里完全移除一个节点,
CLUSTER FORGET
命令必须发送到所有其他主节点和从节点。
However the command cannot simply drop the node from the internal node table of the node receiving the command, it also implements a ban-list, not allowing the same node to be added again as a side effect of processing the gossip section of the heartbeat packets received from other nodes.
但是,该命令不仅仅是简单地从接收命令的节点的内部节点表中删除节点,它还实现了一个禁用列表,禁止将相同节点意外加入到从其他节点接收的心跳信息包中。
Details on why the ban-list is needed
为啥需要禁用列表
In the following example we’ll show why the command must not just remove a given node from the nodes table, but also prevent it for being re-inserted again for some time.
在以下案例中,我们会展示为什么这个命令不能仅从节点列表中移除指定节点,还需要防止这个节点有时被重新插入。
Let’s assume we have four nodes, A, B, C and D. In order to end with just a three nodes cluster A, B, C we may follow these steps:
我们假设我们有4个节点,A,B,C,D。为了使集群最终仅剩A,B,C节点,我们需要执行以下几步:
- Reshard all the hash slots from D to nodes A, B, C.
- D is now empty, but still listed in the nodes table of A, B and C.
- We contact A, and send
CLUSTER FORGET D
. - B sends node A a heartbeat packet, where node D is listed.
- A does no longer known node D (see step 3), so it starts an handshake with D.
- D ends re-added in the nodes table of A.
- 将D节点的槽位全部迁移到A,B,C节点
- D节点成为空节点了,但是仍然在A,B,C的节点列表中。
- 我们联系A节点,然后发送
CLUSTER FORGET D
命令- B想节点A发送心跳包,节点D的信息还在心跳包信息在
- A节点没有D节点信息了,所以开始与D进行握手。
- D节点重新加入了A节点的信息表中
As you can see in this way removing a node is fragile, we need to send CLUSTER FORGET commands to all the nodes ASAP hoping there are no gossip sections processing in the meantime. Because of this problem the command implements a ban-list with an expire time for each entry.
可以看到,这种移出节点的方式很脆,我们需要尽快发送
CLUSTER FORGET
命令到所有节点,并希望在相同时间没有进行gossip交互在进行中。因为这个问题,这个命令实现了一个 禁用列表,列表中的实体都有一个超时时间。
So what the command really does is:
所以命令真正步骤是:
- The specified node gets removed from the nodes table.
- The node ID of the removed node gets added to the ban-list, for 1 minute.
- The node will skip all the node IDs listed in the ban-list when processing gossip sections received in heartbeat packets from other nodes.
- 指定节点从节点表中移出
- 移除的节点ID被加到了禁用列表中,持续一分钟
- 节点在处理接收到其他节点的心跳包的gossip信息时,会跳过禁用列表中所有的的节点id。
This way we have a 60 second window to inform all the nodes in the cluster that we want to remove a node.
这样,我们就有了60秒的时间窗口来通知集群中的所有节点 我们想移除一个节点这个事情。
Special conditions not allowing the command execution
不允许命令执行的特定条件
The command does not succeed and returns an error in the following cases: > 以下情况,命令不回成功,并且会返回错误:
- The specified node ID is not found in the nodes table.
- The node receiving the command is a replica, and the specified node ID identifies its current master.
- The node ID identifies the same node we are sending the command to.
- 指定的节点id在节点表中没有。
- 接收命令的节点是一个副本节点,并且指定的节点ID是它的当前的主节点。
- 要移除的节点ID和我们发送命令的目的节点是同一个。
Return value
返回值
Simple string reply: OK
if the command was executed successfully, otherwise an error is returned.
返回字符串:成功返回
OK
,否则返回错误。