Amazon dynamodb 用于删除操作的DynamoDB流事件中的元数据?

Amazon dynamodb 用于删除操作的DynamoDB流事件中的元数据?,amazon-dynamodb,amazon-dynamodb-streams,Amazon Dynamodb,Amazon Dynamodb Streams,我打算使用DynamoDB streams来实现一个日志跟踪,跟踪对许多表的更改(并将其写入S3上的日志文件)。每当对表进行修改时,都会从流事件调用lambda函数。 现在,我需要记录进行修改的用户。 对于put和update,我可以通过包含一个保存调用方ID的实际表属性来解决这个问题。现在存储在表中的记录将包含这个ID,这并不是真正需要的,因为它更多的是关于操作的元数据,而不是记录本身的一部分,但我可以接受这个 例如: put({ TableName: 'fruits', Item:

我打算使用DynamoDB streams来实现一个日志跟踪,跟踪对许多表的更改(并将其写入S3上的日志文件)。每当对表进行修改时,都会从流事件调用lambda函数。 现在,我需要记录进行修改的用户。 对于
put
update
,我可以通过包含一个保存调用方ID的实际表属性来解决这个问题。现在存储在表中的记录将包含这个ID,这并不是真正需要的,因为它更多的是关于操作的元数据,而不是记录本身的一部分,但我可以接受这个

例如:

put({
  TableName: 'fruits',
  Item: {
    id: 7,
    name: 'Apple',
    flavor: 'Delicious',
    __modifiedBy: 'USER_42'
  })
这将导致lambda函数调用,我可以在S3日志文件中写入如下内容:

table: 'fruits',
operation: 'put',
time: '2018-12-10T13:35:00Z',
user: 'USER_42',
data: {
    id: 7,
    name: 'Apple',
    flavor: 'Delicious',
}
但是,对于删除,会出现一个问题-如何记录删除操作的调用用户?当然,我可以发出两个请求,一个更新
\uuuu modifiedBy
,另一个删除该项,流将只从流事件中包含的
旧图像
中获取
\uu modifiedBy
值。然而,这确实是不可取的,必须在一次删除一个项目上花费2次写入


那么,有没有更好的方法,比如将元数据附加到DynamoDB操作中,这些操作会被带入流事件中,而不会成为写入表本身的数据的一部分呢?

这里有3个不同的选项。正确的选择取决于您的应用程序的要求。可能这些方法都不能在您的特定用例中工作,但一般来说,这些方法都能工作

选项1

如果您使用的AWS IAM粒度足够细,那么您可以从中获取用户标识

选项2

如果在写入dynamodb时可以处理少量开销,那么可以设置一个lambda函数(或基于ec2的服务),作为dynamodb表的写入代理。配置您的权限,以便只有Lambda可以写入表中,然后您可以接受所需的任何元数据,并以任何方式记录它。如果您只需要记录事件,那么就不需要写入S3,因为AWS可以为您处理Lambda日志

下面是一个lambda函数的伪代码示例,它使用日志记录而不是写入S3

handle_event(operation, item, user)
    log(operation, item, user)
    switch operation
        case put:
             dynamodb.put(item)
        case update:
             dynamodb.update(item)
        case delete:
             dynamodb.delete(item)

log(operation, item, user)
    logEntry.time = now
    logEntry.user = user
    ...
    print(logEntry)
当然,您仍然可以自由地直接登录到S3,但如果您这样做,您可能会发现增加的延迟足以影响您的应用程序

选项3

如果您可以容忍表中的某些陈旧数据,请在表上进行设置。创建或更新项目时不要设置TTL值。然后,通过将当前时间添加到TTL字段来更新项目,而不是删除项目。据我所知,DynamoDB在删除具有过期TTL的项目时不使用写容量,过期的项目在其过期24小时后被删除

这将允许您将“添加TTL”记录为删除,并让用户上次修改该删除。您可以安全地忽略dynamodb清除过期项目时发生的实际删除


在应用程序中,还可以检查TTL值是否存在,这样就不会意外地向用户显示已删除的数据。您还可以向任何将忽略具有TTL集的项的查询添加筛选器表达式

这些都是很好的建议,谢谢。我曾考虑过选项1),但我没有使用那种IAM设置,所以我需要一个来自我的应用层的自定义用户id,作为所有操作的“作者”登录。选项3是我根本没有考虑过的,这真的很好。但是,我必须更改很多其他查询,以从结果集中排除TTL:ed项,这可能会让我感到有些头痛。如果我从零开始做一些事情,我可能会使用这个解决方案。保留选项2,我可能最终会做它的一个变体,但我可能会在客户端做,而不是在云中运行一个封装db调用的API层。事实上,我的所有数据库调用都已经有了一个layer/DB包装器,而不是从Dynamo触发,我可以直接从那里提交事件。虽然我更愿意将日志跟踪与应用程序逻辑分离,但这最终可能是最简单的。缺点是,任何潜在的“直接”DynamoDB调用都会在没有记录的情况下潜入,但如果所有操作都使用自定义格式,则streams和lambda函数也可能如此(包括modifiedTime、modifiedBy、使用TTL的自定义删除方案等),所以这可能不是一个真正的问题。如果使用带有lambda函数的选项2作为代理,实际上可以防止任何“偷偷摸摸”的行为通过设置IAM策略阻止所有dynamodb PUT、更新和删除(如果不是来自该lambda函数)绕过代理的调用。选项3也可以通过代理实现,这可能有助于限制需要更改代码的位置数。我认为选项1不适用。userIdentity字段为使用TTL字段仅删除填充了记录的字段。在所有其他情况下,字段UserIdentity在记录中不可用