了解Akka群集分片

时间:2020-07-12 13:45:20

标签: java scala akka sharding akka-cluster

我正在学习Akka分片模块。 我有些不了解Sharding。 假设您要分派一个actor:您有来自同一actor的许多实体分布在许多节点上。 每个实体可以具有其自己的状态,该状态可以不同于另一个实体。

客户端正在向分片actor发出请求(发送消息)以获取其状态值。该消息将由实体处理并作为结果返回其值。但是,如果由另一个实体对其进行处理,结果将有所不同。 但这应该是相同的,因为所有实体都来自同一演员,不是吗?

3 个答案:

答案 0 :(得分:3)

似乎您误解了Akka集群分片的概念,让我举一个例子进行说明。

假设您的服务负责使用用户个人资料响应请求。为了获得极低的延迟,您决定使用Akka actor将用户配置文件缓存在内存中,而不必每次请求都查询数据库。

如果您的网站只有10个用户,并且每个用户配置文件只有几个KB,则您可以将所有10个用户配置文件保存在一个actor中,而不会出现问题,并且您肯定不需要群集分片。但是,如果您有1000万用户,则可能有1000万用户配置文件无法放入单个actor的内存中,而当actor崩溃时,这也很昂贵,因为这意味着您需要大型数据库查询才能获取这些数据来自持久性。

在这种情况下,群集分片是合适的。您将有1000万个Akka actor,分布在整个群集中,每个actor仅存储1个用户配置文件。因此,GetUserProfile(userProfileId = 123)不会给您不同的响应-它总是被路由到拥有用户123用户档案的演员,因此响应始终是相同的。

路由如何工作?在doc

中检查extractShardIdextractEntityId

答案 1 :(得分:0)

但是[消息响应]应该相同,因为所有实体都来自同一演员,不是吗?

不,每个演员都有自己的状态并代表不同的事物。如果您有一个Customer类,则不会期望每个Customer对象都具有相同的数据。每个客户对象都有其自己的名称,ID等。

演员也是如此。参与者具有自己的状态,并代表某种领域实体。如果您向演员发送GetCustomerName消息,那么您希望每个演员给您起一个不同的名字。

对于集群分片尤其如此。群集分片的目的是使您可以扩展到单个节点:可伸缩性,弹性或弹性。但是他们仍然是演员,每个演员都有自己的状态。发送GetCustomerName将(并且应该)给您每个不同角色的不同答复。分片功能使您能够在多个计算机上分布这些参与者,并使参与者的位置对发送者透明。

答案 2 :(得分:0)

在Akka群集分片中,每个参与者都应具有唯一的名称(通常是实体ID)并代表一个唯一的实体。当actor启动/重启实体(通常从数据库)加载到actor状态时。

如果参与者收到消息以更新实体,则参与者应更新数据库和参与者状态;如果参与者收到消息以读取实体,则参与者应仅从参与者状态读取实体(保证与实体状态相同)。数据库,因为所有更新操作仅由一个参与者执行。

如果任何节点发生故障或在集群扩展的情况下,则可以在另一个节点(碎片区域)上重新创建与所请求实体相对应的actor。