分片概览
集群配置
每个正在运行的集群实例都维护着一份集群配置的本地副本。此副本包含有关已知集群工作节点和相关槽分配的信息。这两部分信息都使用结构体数组表示,如下所示。本地副本的更改通过八卦协议(gossiping)传播到集群中的其他节点。
请注意,与节点特性相关的信息只能由节点本身通过发出相关的集群命令进行更新。例如,一个节点不能通过接收八卦消息成为**REPLICA**。它只能在收到`CLUSTER REPLICATE`请求后才能更改其当前角色。我们遵循此限制,以避免在网络分区事件中处理集群配置错误。此约定也适用于槽分配,槽分配通过使用`CLUSTER [ADDSLOTS|DELSLOTS]`和`CLUSTER [ADDSLOTSRANGE|DELSLOTSRANGE]`命令直接向集群实例发出请求来管理。
loading...
最初,集群节点为空,扮演**PRIMARY**角色,没有分配的槽位,也不知道集群中的任何其他节点。本地节点只包含存储在 workers[1] 中的自身信息,而 workers[0] 保留用于特殊用途,以指示未分配的槽位。Garnet 集群节点通过`CLUSTER MEET`命令相互连接,该命令会生成一种特殊类型的八卦消息。此消息强制远程节点将发送方添加到其受信任节点列表。远程节点以任意顺序存储,从 workers[2] 开始。
loading...
有关单个槽分配的信息通过配置对象中的 HashSlot 结构体类型数组捕获。它维护有关槽状态和相应所有者的信息。槽所有者使用 workers 数组本地副本中的偏移量表示。槽状态用于确定如何处理映射到相关槽的键的请求。
loading...
在集群启动时,槽是未分配的,因此它们的初始状态设置为**OFFLINE**,workerId 设置为 0。当一个槽分配给特定节点时,其状态设置为**STABLE**,workerId(从本地配置副本的角度来看)设置为所有者节点在 workers 数组中的相应偏移量。槽的所有者可以对与该特定槽关联的数据执行读/写和迁移操作。副本只能为由其主节点拥有的槽所映射的键提供读请求。
loading...
配置更新传播
给定节点将接受来自受信任节点的八卦消息。八卦消息将包含一个序列化的字节数组表示,该表示代表远程节点本地配置的快照。接收节点将尝试通过比较相关工作节点的配置纪元(epoch)来原子地将其传入配置合并到其本地副本。因此,集群配置的任何更改都可以在单个工作节点的粒度上发生。我们利用此机制来控制本地更新何时对集群的其余部分可见。这对于持续时间长且包含多个阶段的操作(例如数据迁移)非常有用。此类操作容易受到中断,需要保护措施以防止数据完整性受到任何损害。
如前所述,本地更新通过八卦(gossiping)传播,八卦可以以广播模式或八卦采样模式运行。在前一种情况下,我们定期向集群中的所有节点广播配置,而在后一种情况下,我们随机选择一部分节点进行八卦。这可以在服务器启动时通过使用***--gossip-sp***标志进行配置。
槽验证
RESP 数据命令在单个键或一组键上操作。此外,它们可以分类为只读(例如 *GET* mykey)或读写(例如 *SET* mykey foo)。在集群模式下操作时,在处理任何命令之前,Garnet 会执行额外的槽验证步骤。槽验证涉及检查与给定命令关联的键或键,并验证它是否映射到可以由接收关联请求的节点服务的槽。Garnet 主节点可以为其拥有的槽提供*读*和*读写*请求,而 Garnet 副本节点只能为其主节点拥有的槽提供读请求。如果槽验证步骤失败,则相应的命令将不被处理,并且槽验证方法将直接向网络缓冲区写入重定向消息。
loading...
重定向消息
从单个节点的角度来看,任何请求映射到未分配槽位的键都将导致`-CLUSTERDOWN Hashlot not served`消息。对于单个键请求,如果接收节点拥有该槽位,则该已分配槽位被视为**LOCAL**,否则它被归类为**REMOTE**槽位,因为它由远程节点拥有。在下表中,我们提供了根据槽位状态和正在执行的操作类型生成的不同重定向消息的摘要。对于映射到**REMOTE**槽位的特定键的只读和读写请求,将导致`-MOVED
操作/状态 | 已分配本地 | 已分配远程 | 迁移中存在 | 迁移中不存在 | 导入中请求 | 导入中未请求 |
---|---|---|---|---|---|---|
只读 | 正常 | -MOVED | 正常 | -ASK | 正常 | -MOVED |
读写 | 正常 | -MOVED | -MIGRATING | -ASK | 正常 | -MOVED |