【问题标题】:how to implement an atomic counter in aws如何在aws中实现原子计数器
【发布时间】:2022-01-30 01:31:15
【问题描述】:

我需要在 aws 中实现一种票务系统,仅使用无服务器技术。该功能需要有点像邮局的数字系统:你拿一张票,上面有一个号码。作为请求者,您知道自己的号码。滚动移动,下一位客户得到一个加一的数字。此票证将由 lambda 函数中的处理程序请求,该函数可以并行调用。我知道这听起来像是全局锁,确实如此,但这是要求 - 请不要告诉我重新设计我的用例,这样就没有必要了。

非功能性需求:

  • 应该是全局一致的
  • 应该是高性能的,即。每秒可能有数百个或理想情况下数千个请求
  • 一致:没有重复的数字
  • 失败是可以的,重试是可以的,只要保持一致性。

我尝试过的:

  • Dynamodb:我使用 go sdk 和这个 "cirello.io/dynamolock" 包实现了一个分布式锁。它可以工作,但锁定/解锁周期需要 700 毫秒 - 太慢了。
  • 还有 Dynamodb:我在 an UpdateItem 调用中使用了 UpdateExpressionReturnValues,但在数据中心内仍然只有 125/秒。
  • 弹力痛。无法让它工作,因为设置 VPC 以连接 lambda 的复杂性,然后失去与 dynamodb 的连接。我听说您可以使用 NAT 网关解决此问题,但到那时,您的无服务器框架应用程序开始看起来非常复杂,对于计数器而言非常复杂。

【问题讨论】:

标签: amazon-web-services amazon-dynamodb mutex amazon-elasticache


【解决方案1】:

DynamoDB 最多支持每秒对单个分区进行 1000 次写入。如果这是可接受的性能,正确的 DynamoDB 调用是:

dynamoDB.update({
  TableName: "my-atomic-counter-db",
  Key: "my-ticket-counter",
  ReturnValues: "UPDATED_NEW",
  UpdateExpression: `SET #value = if_not_exists(#value, :start) + :increment`,
  ExpressionAttributeValues: {
    ':start': 0,
    ':increment': 1,
  },
  ExpressionAttributeNames: {
    '#value': 'value',
  },

如果您需要支持每秒超过 1000 个工单,您可以将“增量”计数器增加到更大的数字,并以批处理的方式回答“工单请求”。比如通过SQS发送ticket请求,分批读取10条消息,以10的增量调用dynamoDB,读取最高ticket的返回值,从T...T-10分发ticket。

【讨论】:

  • 这就是我在上面第二个要点中所做的。公平地说,性能优于每秒 7 个 - 我设法在大约 800 毫秒内获得了大约 100 个新票。但它仍然出奇地慢。
  • SQS 的想法很有趣——我试试看,如果可行,请接受这个答案。
猜你喜欢
  • 1970-01-01
  • 2013-01-05
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多