如何在aws中实现原子计数器



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

非功能要求:

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

我尝试过的:

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

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发送票证请求,以10为一批读取消息,以10的增量值调用dynamoDB,读取最高票证的返回值,并从T…T-10分发票证。

最新更新