ShardRegion actor在群集中的每个节点或标记有特定角色的节点组上启动。使用两个特定应用程序的函数创建ShardRegion,以从传入消息中提取实体标识符和分片标识符。分片是一起管理的一组实体。对于特定分片中的第一条消息,ShardRegion向中央协调器ShardCoordinator请求分片的位置。
ShardCoordinator决定哪个ShardRegion拥有该Shard,并通知该ShardRegion。该region将确认此请求并创建Shard监管者作为子actor。然后,在Shard actor需要时将创建各个实体。因此,传入消息通过ShardRegion和Shard到达目标实体。
如果分片宿主是另一个ShardRegion实例,则将消息转发到该ShardRegion实例。在解析分片的位置时,对该分片的传入消息进行缓冲,然后在知道分片宿主时进行传递。后续到已解析分片的消息可以立即传递到目标目的地,而无需涉及ShardCoordinator。
场景
一旦知道了分片的位置,ShardRegions就会直接发送消息。如下达到此状态的场景。在场景中,使用以下表示法:
- SC-分片协调员
- M#-消息1、2、3等
- SR#-ShardRegion 1、2 3等
- S#-分片1 2 3等
- E#-实体1 2 3,等等。实体是指由集群分片管理的Actor。
#
是一个数字,用于区分实例,因为集群中有多个实例。
场景1:发送消息到本地ShardRegion的未知分片
1.传入消息M1到ShardRegion实例SR1。
2.M1映射到分片S1。 SR1不知道S1,因此向SC询问S1的位置。
3.SC回答S1的来自SR1。
4.SR1创建子actor代表分片S1,并将消息转发给它。
5.S1为E1创建子actor,并将消息转发给它。
6.SR1可以处理所有到达SR1的传入S1的消息,而无需SC。
场景2:消息发送到远程ShardRegion的未知分片
1.消息M2传入ShardRegion实例SR1。
2.M2映射到S2。 SR1不了解S2,因此向SC询问S2的位置。
3.SC回答S2的来自SR2。
4.SR1向S2发送为SR2的缓冲消息。
5.SR1可以在没有SC的情况下,处理到达SR1的传入S2的所有消息。它将消息转发到SR2。
6.SR2收到有关S2的消息,询问SC,它回答S2的来自SR2,如场景1描述的。
分片位置
为了确保特定实体actor的最多一个实例在集群中的某处运行,重要的是所有节点对分片的位置具有相同的看法。因此,分片分配决定由中央ShardCoordinator决定,中央ShardCoordinator作为集群单例运行,即所有集群节点中或标记有特定角色的一组节点中的最老的一个实例。
在可插拔shard allocation strategy中定义了决定分片位于何处的逻辑。
分片再平衡
为了能够使用集群中新添加的成员,协调器利用分片的重新平衡,即将实体从一个节点迁移到另一个节点。在重新平衡过程中,协调器首先通知所有ShardRegion actors,已开始为分片进行切换。这意味着它们将开始缓冲该分片的传入消息,就像分片位置未知一样。在重新平衡过程中,协调器将不回答任何请求在重新平衡的分片位置的请求,即本地缓冲将继续进行,直到切换完成为止。负责重新平衡分片的ShardRegion将通过向其发送指定的stopMessage(默认PoisonPill)来停止该分片中的所有实体。当所有实体都终止后,拥有实体的ShardRegion将向协调员确认切换已完成。此后,协调器将回复对分片位置的请求,从而为分片分配新的位置,然后将ShardRegion actor中的缓冲消息传递到新位置。这意味着实体的状态不会被传输或迁移。如果实体的状态很重要,则它应该是持久的(持久化),例如使用持久性(或参见经典持久性),以便可以在新位置恢复它。
可插拔分片分配策略中定义了决定重新分片的逻辑。默认实现ShardCoordinator.LeastShardAllocationStrategy从具有最多先前分配的分片数量的ShardRegion中选择分片进行切换。然后将它们分配给具有最少数量先前分配的分片的ShardRegion(即群集中的新成员)。
对于LeastShardAllocationStrategy,有一个可配置的阈值(rebalance-threshold),该阈值要求开始进行重新平衡时必须相差多大。分片最多的区域和分片最少的区域中的分片数量之差必须大于重新平衡阈值才能发生重新平衡。
重新平衡阈值1给出最佳分布,因此通常是最佳选择。较高的阈值意味着可以同时重新平衡更多的分片,而不是一个接一个。这可以使重新平衡过程更快,但是不同节点之间的分片(因此负载)数量可能显着不同。
ShardCoordinator状态
ShardCoordinator中的分片位置状态对于分布式数据(或参见经典分布式数据)是持久(持久)的,以应对故障。
从集群中删除(通过故障)崩溃或无法访问的协调器节点后,新的ShardCoordinator单例actor将接管并恢复状态。在这样的故障期间,具有已知位置的分片仍然可用,而发送给新(未知)分片的消息将被缓冲,直到新的ShardCoordinator可用为止。
消息排序
只要发件人使用相同的ShardRegion actor将消息传递到实体actor,就将保留消息的顺序。只要未达到缓冲区限制,就以尽力而为的方式发送消息,并具有至多一次的发送语义,方式与普通消息发送相同。
可靠传递
通过使用“可靠传递”功能,可以添加具有至少一次语义的可靠的端到端消息传递。
开销
由于与协调器的往返路程,针对以新的或先前未使用的分片为目标的消息引入了一些额外的延迟。分片的重新平衡也可能会增加延迟。在设计应用程序特定的分片分辨率(例如,避免太细的分片。知道分片的位置后,唯一的开销就是通过ShardRegion而不是直接发送消息。