我正在学习Akka分片模块。 我有些不了解Sharding。 假设您要分派一个actor:您有来自同一actor的许多实体分布在许多节点上。 每个实体可以具有其自己的状态,该状态可以不同于另一个实体。
客户端正在向分片actor发出请求(发送消息)以获取其状态值。该消息将由实体处理并作为结果返回其值。但是,如果由另一个实体对其进行处理,结果将有所不同。 但这应该是相同的,因为所有实体都来自同一演员,不是吗?
答案 0 :(得分:3)
似乎您误解了Akka集群分片的概念,让我举一个例子进行说明。
假设您的服务负责使用用户个人资料响应请求。为了获得极低的延迟,您决定使用Akka actor将用户配置文件缓存在内存中,而不必每次请求都查询数据库。
如果您的网站只有10个用户,并且每个用户配置文件只有几个KB,则您可以将所有10个用户配置文件保存在一个actor中,而不会出现问题,并且您肯定不需要群集分片。但是,如果您有1000万用户,则可能有1000万用户配置文件无法放入单个actor的内存中,而当actor崩溃时,这也很昂贵,因为这意味着您需要大型数据库查询才能获取这些数据来自持久性。
在这种情况下,群集分片是合适的。您将有1000万个Akka actor,分布在整个群集中,每个actor仅存储1个用户配置文件。因此,GetUserProfile(userProfileId = 123)
不会给您不同的响应-它总是被路由到拥有用户123用户档案的演员,因此响应始终是相同的。
路由如何工作?在doc
中检查extractShardId
和extractEntityId
答案 1 :(得分:0)
但是[消息响应]应该相同,因为所有实体都来自同一演员,不是吗?
不,每个演员都有自己的状态并代表不同的事物。如果您有一个Customer类,则不会期望每个Customer对象都具有相同的数据。每个客户对象都有其自己的名称,ID等。
演员也是如此。参与者具有自己的状态,并代表某种领域实体。如果您向演员发送GetCustomerName
消息,那么您希望每个演员给您起一个不同的名字。
对于集群分片尤其如此。群集分片的目的是使您可以扩展到单个节点:可伸缩性,弹性或弹性。但是他们仍然是演员,每个演员都有自己的状态。发送GetCustomerName
将(并且应该)给您每个不同角色的不同答复。分片功能使您能够在多个计算机上分布这些参与者,并使参与者的位置对发送者透明。
答案 2 :(得分:0)
在Akka群集分片中,每个参与者都应具有唯一的名称(通常是实体ID)并代表一个唯一的实体。当actor启动/重启实体(通常从数据库)加载到actor状态时。
如果参与者收到消息以更新实体,则参与者应更新数据库和参与者状态;如果参与者收到消息以读取实体,则参与者应仅从参与者状态读取实体(保证与实体状态相同)。数据库,因为所有更新操作仅由一个参与者执行。
如果任何节点发生故障或在集群扩展的情况下,则可以在另一个节点(碎片区域)上重新创建与所请求实体相对应的actor。