分片计数器的高级设计


让我们了解和设计分片计数器。

高级解决方案概述

管理数百万条推特点赞需要许多计数器在许多节点上运行。为了管理这些计数器,我们需要一个高效的系统,它可以随着用户数量的增长提供高性能和可扩展性。

当Twitter上的单个推文获得一百万个赞,并且应用服务器接收到针对每个赞的写入请求以增加相关计数器时,会发生什么?这些数百万个请求最终会在队列中串行化以确保数据一致性。这种串行化是处理并发活动的一种方式,但代价是增加延迟。实时应用程序希望通过为终端用户提供尽可能短的延迟来保持体验质量高。

让我们看一下下面的示例以了解这个问题:

QQ截图20230410160240

单个名人发布的每条推文的计数器不足以处理数百万用户。这个问题的解决方案是 分片计数器,也称为分布式计数器,其中每个计数器具有需要的特定数量的分片。这些分片并行运行在不同的计算单元上。通过将数百万个写入请求分配到不同的分片上,我们可以提高性能并减少争用。

首先,当用户点赞某个推文时,写入请求被转发到指定的推文计数器。然后,系统选择一个可用的指定推文计数器的分片来增加点赞计数器的值。让我们看一下下面的示例,以了解具有指定分片的分片计数器:

QQ截图20230410160359

在上面的示例中,每个计数器的总分片数为(N+1)。根据我们的需求,我们将使用适当的值来代替N。让我们讨论一个示例,以了解分片计数器如何处理单个帖子的数百万个写入和读取请求。

假设一个拥有数百万订阅者的著名YouTube频道上传了一个新视频。服务器从全球用户接收到视频观看量的一大批写入请求。首先,为新上传的视频初始化一个新计数器。服务器将请求转发到相应的计数器,我们的系统随机选择一个可用的分片来更新计数器的值,该值最初为零。相反,当服务器接收到读取请求时,它将添加计数器的所有分片的值,以获取当前总数。

我们可以为需要可扩展计数的每种情况(如Facebook帖子和YouTube视频)使用分片计数器。

分片计数器的API设计

本节讨论将调用分片计数器的API。我们的API设计将帮助我们了解分片计数器和其调用者之间的交互。为了使我们的讨论具体化,我们将在Twitter的上下文中讨论每个API功能。让我们为以下每个功能开发API:

  • 创建计数器
  • 写计数器
  • 读计数器

虽然上述API功能列表不是详尽无遗的,但它们代表了一些最重要的功能之一。

创建计数器

\createCounter API初始化了一个可用于计数的分布式计数器。\createCounter API如下所示:

scssCopy code
createCounter(counter_id, number_of_shards)
参数描述
counter_id它代表计数器的唯一ID。调用此API的调用方可以使用一个序列器来获取唯一标识符。有关详情,请参阅序列器构建块课程。
number_of_shards它指定计数器的分片数量。

我们可以使用适当的数据存储来保留我们的元数据,包括计数器标识符、它们的分片数量和分片到物理机器的映射。

让我们以Twitter为例,了解应用程序如何使用上述API。当用户在社交媒体上发布内容时,\createCounter API用于创建计数器。例如,如果用户在Twitter上发布了一条推文,应用程序服务器将调用\createCounter API。content_type参数是系统用于确定需要创建的计数器数量的帖子类型。例如,仅在推文包含视频剪辑时,系统需要视图计数器。

为了找到适当的number_of_shards值,我们可以使用以下启发式算法:

  • followers_count参数表示发布推文的用户的关注者计数。
  • post_type参数指定帖子是公开的还是受保护的。受保护的推文仅适用于关注者,这种情况下我们更好地预测分片数量。

写计数器

当我们想要增加(或减少)计数器时,\writeCounter API用于此。实际上,计数器的特定分片会被增加或减少,我们的服务会根据多个因素进行决策,稍后我们将讨论这些因素。\writeCounter API如下所示:

scssCopy code
writeCounter(counter_id, action_type)
参数描述
counter_id它是唯一标识符(在计数器创建时提供)。
action_type它指定所需操作(增加或减少计数器的值)。我们从数据存储中提取有关计数器的所需信息。

在我们的Twitter示例中,当用户对其他人的帖子或自己的帖子进行操作时(例如点赞、回复等),会使用\writeCounter API。

读计数器

当我们想要知道计数器的当前值时,使用\readCounter API。我们的系统从数据存储中获取适当的信息以从所有分片收集值。\readCounter API如下所示:

scssCopy code
readCounter(counter_id)
参数描述
counter_id它是唯一标识符(在计数器创建时提供)。对于Twitter,counter_id将基于以下指标决定:tweet_id指定请求生成的推文的唯一ID。我们可以使用tweet_id获取所有特征(点赞、转发等)的计数器的counter_id

当用户想要查看特定推文的点赞数或查看次数时,会调用\readCounter API。通常,当用户想要查看他们的主页或用户时间轴时,会触发此API。

下一节将讨论在调用所有上述API时后端系统中发生的情况。