Amazon dynamodb Dynamodb线程安全更新

Amazon dynamodb Dynamodb线程安全更新,amazon-dynamodb,thread-safety,Amazon Dynamodb,Thread Safety,Lambda函数由SQS消息触发。保留并发被设置为最大值,这意味着我可以同时执行Lambda。每个Lambda将读取SQS消息,并需要更新一个包含消息长度总和的Dynamodb表。这是一个增加的数值。 虽然我已经实现了乐观锁定,但我仍然看到最终值与实际的正确总和不匹配。有什么想法吗 以下是执行更新的代码: public async Task Update(T item) { using (IDynamoDBContext dbContext = _dataContextF

Lambda函数由SQS消息触发。保留并发被设置为最大值,这意味着我可以同时执行Lambda。每个Lambda将读取SQS消息,并需要更新一个包含消息长度总和的Dynamodb表。这是一个增加的数值。 虽然我已经实现了乐观锁定,但我仍然看到最终值与实际的正确总和不匹配。有什么想法吗

以下是执行更新的代码:

public async Task Update(T item)
    {
        using (IDynamoDBContext dbContext = _dataContextFactory.Create())
        {
            T savedItem = await dbContext.LoadAsync(item);

            if (savedItem == null)
            {
                throw new AmazonDynamoDBException("DynamoService.Update: The item does not exist in the Table");
            }

            await dbContext.SaveAsync(item);
        }
    }

这里最好使用DynamoDB流和批处理写入。否则,您将不可避免地遇到事务冲突,可能在某些日志中的某个地方存在大量错误。您还可以看到表的cloudwatch度量:
TransactionConflict

DynamoDB流

要执行聚合,您需要有一个启用了流的表。将
MaximumBatchingWindowInSeconds
BatchSize
设置为适合您要求的值。也就是说,您需要能够在10秒内准确显示,您可以将
MaximumBatchingWindowInSeconds
设置为不超过10。您可能不希望有超过100个项目等待聚合,因此设置
BatchSize=100
。您将创建一个Lambda函数,该函数将以以下形式处理进入表中的项目:

"TransactItems": [{
  "Put": {
    "TableName": "protect-your-table",
    "Item": {
      "id": "123",
      "length": 4,
....
然后,您将对此进行迭代,并对
length
属性求和,然后对另一个表中的求和执行更新
ADD
语句,该表保存基于流的计算统计信息。注意:您可能会收到重复的消息,这可能会导致您出错。您可以在Dynamo中处理此问题,方法是确保您不编写已经存在的项,或者使用

配料

确保你不是一次处理一条小消息,而是将它们批处理在一起,比如在你的Lambda函数中,它读取表单SQS,一次最多可以读取100条消息并进行批处理写入。同时设置一个低的并发限制,这样消息就可以在几秒钟内堆积起来


您希望这样做的原因是,您实际上无法每秒多次增加DynamoDB中的值,这会给您带来错误,并实际降低处理速度。您会发现您的系统总体上的运行成本较低,更加准确,而且实时精度应该足够接近您的需要。

最好在此处使用DynamoDB流和批写入。否则,您将不可避免地遇到事务冲突,可能在某些日志中的某个地方存在大量错误。您还可以看到表的cloudwatch度量:
TransactionConflict

DynamoDB流

要执行聚合,您需要有一个启用了流的表。将
MaximumBatchingWindowInSeconds
BatchSize
设置为适合您要求的值。也就是说,您需要能够在10秒内准确显示,您可以将
MaximumBatchingWindowInSeconds
设置为不超过10。您可能不希望有超过100个项目等待聚合,因此设置
BatchSize=100
。您将创建一个Lambda函数,该函数将以以下形式处理进入表中的项目:

"TransactItems": [{
  "Put": {
    "TableName": "protect-your-table",
    "Item": {
      "id": "123",
      "length": 4,
....
然后,您将对此进行迭代,并对
length
属性求和,然后对另一个表中的求和执行更新
ADD
语句,该表保存基于流的计算统计信息。注意:您可能会收到重复的消息,这可能会导致您出错。您可以在Dynamo中处理此问题,方法是确保您不编写已经存在的项,或者使用

配料

确保你不是一次处理一条小消息,而是将它们批处理在一起,比如在你的Lambda函数中,它读取表单SQS,一次最多可以读取100条消息并进行批处理写入。同时设置一个低的并发限制,这样消息就可以在几秒钟内堆积起来


您希望这样做的原因是,您实际上无法每秒多次增加DynamoDB中的值,这会给您带来错误,并实际降低处理速度。您会发现,您的系统总体上的运行成本仅为成本的一小部分,更加精确,而且实时精度应该足够接近您所需要的。

谢谢您的回答@Snickers33192。我扫描了整个日志,没有事务冲突或条件检查失败异常。我将查看DynamoDB流,并将我的评论放在此处检查ThrottlingException!我喜欢你的建议,但仍然无法说服自己减少并发性。我们每天至少有100万次活动,而且这个数字呈指数增长。我们也验证每一条信息,并在其中有一个微小的逻辑,这不仅仅是摄入。流媒体的主要问题是lambda无法保持对@Snickers33192答案的上扬。我扫描了整个日志,没有事务冲突或条件检查失败异常。我将查看DynamoDB流,并将我的评论放在此处检查ThrottlingException!我喜欢你的建议,但仍然无法说服自己减少并发性。我们每天至少有100万次活动,而且这个数字呈指数增长。我们也验证每一条信息,并在其中有一个微小的逻辑,这不仅仅是摄入。流媒体的主要问题是lambda无法跟上