DynamoDB流-将数据写回到表中

时间:2018-12-30 03:21:47

标签: amazon-web-services amazon-dynamodb

请考虑以下架构:

write -> DynamoDB table -> stream -> Lambda -> write metadata item to same table 

它可以用于许多非常糟糕的情况,例如表和项目级别的聚合。我已经看到官方AWS工程师在几次技术讲座中推广了这种架构。


但是编写元数据项不是将新项添加到流中并再次运行Lambda吗?

如何避免无限循环?有没有一种方法可以避免元数据写入流中?

在这种架构下,花费2个流和Lambda请求是不可避免的吗? (我们会根据请求收取费用),即如果它是元数据项,则提前退出Lambda函数。

3 个答案:

答案 0 :(得分:2)

由于从DynamoDB流触发AWS Lambda函数是一个二进制选项(开/关),因此不可能仅对表的某些写入触发AWS Lambda函数。因此,将针对刚刚写入DynamoDB表的项目再次调用您的AWS Lambda函数。重要的一点是在您的AWS Lambda函数中具有适当的逻辑,以检测到它已写入该数据,并且在这种情况下不再写入数据。否则,您将得到提到的无限循环,这将是非常不幸的情况,尤其是如果它不被注意的话。

答案 1 :(得分:0)

当前dynamo DB不提供基于条件的流订阅,因此,是的,Dynamo DB将在无限循环中执行lambda函数,当前唯一的解决方案是限制lambda函数的执行时间,您可以使用多个lambda函数,一个lambda函数将仅用于检查是否写入了元数据,我正在共享一个云体系结构图,说明如何实现它,

Dynamo DB same table metadata insertion reference

答案 2 :(得分:0)

有点晚了,但希望人们寻求更具示范性的答案会发现这很有用。

假设您要处理要添加到某个项目的记录,且该记录不超过特定阈值,则可以使用if条件来检查并处理或跳过该记录,例如

此代码假定您为每个实体/对象类型都具有一个属性“ Type”-Rick Houlihan本人向我推荐了该属性,但是您也可以检查属性是否存在,例如"<your-attribute>" in record["dynamodb"]["NewImage"]-并且您是用PK和SK作为通用主键和排序键名进行设计。

threshold = (os.environ.get("THRESHOLD"))


def get_value():
    response = table.query(KeyConditionExpression=Key('PK').eq(<your-pk>))
    value = response['Items']['<your-attribute>'] if 'Items' in response else 0
    return value


def your_aggregation_function():
    # Your aggregation logic here
    # Write back to the table with a put_item call once done


def lambda_handler(event, context):
    for record in event['Records']:
        if record['eventName'] != "REMOVE" and record["dynamodb"]["NewImage"]["Type'] == <your-entity-type>:
            # Query the table to extract the attribute value
            attribute_value = get_value(record["dynamodb"]["Keys"]["PK"]["S"])
            if attribute_value < threshold:
                # Send to your aggregation function 

在lambda处理程序中具有适当的条件(或者您可以更改满足自己需求的位置)可以防止出现无限循环。

您可能希望在更新表达式中进行其他检查,以确保两个(或多个)并发的lambda不会写入同一对象。建议您使用date = # timestamp defined in the lambda并将其添加到SK中,或者,如果不能,则在项目中添加“ EventDate”属性,以便您可以添加ConditionExpressionUpdateExpression SET if_not_exists(#attribute, :date)

以上内容将确保您的lambda为idempotent