了解 Akka 集群分片

Understanding Akka cluster sharding

我正在学习 Akka 分片模块。 关于分片,我有些不明白。 让我们想象一下你想要分片一个演员:你有许多来自同一个演员的实体分布在许多节点上。 每个实体都可以有自己的状态,这可能与另一个实体不同。

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

但是[消息响应]应该是相同的,因为所有实体都来自同一个参与者,不是吗?

不,每个演员都有自己的状态,代表不同的东西。如果您有一个 Customer class,您不会期望每个 Customer 对象都具有相同的数据。每个客户对象都有自己的名称、ID 等。

A​​ctor也是如此。 Actor 有自己的状态并代表某种领域实体。如果您向演员发送 GetCustomerName 消息,您会期望每个演员给您一个不同的名字。

集群分片尤其如此。 Cluster Sharding 的要点是您可以扩展到单个节点:无论是为了可扩展性、弹性还是弹性。但他们仍然是每个都有自己状态的Actor。发送 GetCustomerName 将(并且应该)给你来自不同演员的不同回应。分片只是让您能够将这些参与者分布在多台机器上,并让参与者的位置对发送者透明。

看来你对Akka集群分片的概念理解有误,我举个例子说明一下。

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

如果您的网站只有 10 个用户并且每个用户配置文件只有几 KB,您可以毫无问题地将所有 10 个用户配置文件保存在一个参与者中,并且您肯定不需要集群分片。但是,如果您有 1000 万用户,那么 1000 万用户配置文件可能无法放入单个 actor 的内存中,而且如果 actor 宕机,成本会很高,因为这意味着您需要大型数据库查询才能取回这些数据来自坚持。

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

路由是如何工作的?检查 extractShardIdextractEntityIddoc

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

如果一个actor接收到更新实体的消息,那么actor应该更新数据库和actor状态,如果一个actor接收到读取实体的消息,那么actor应该只从actor状态读取实体(保证是一样的)就像在数据库中一样,所有更新操作仅由一个参与者处理)。

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