DynamoDB Streams
DynamoDB Streams 是一份变更数据捕获日志:表上的每一次插入、更新和删除都会被按顺序捕获, 成为一条你可以据以反应的记录流。这就是你在不轮询表的情况下把一张表变成事件源的方式。
在审计日志的场景中,你希望在敏感事件落地的那一刻就做出反应 —— 当有人导出一张发票或授予一个 管理员角色时触发告警 —— 而不必定时扫描表。Streams 就是这件事的推送侧。
DynamoDB Streams 如何工作?
DynamoDB Streams 将表上的每一次插入、更新和删除捕获为一份按时间排序、去重的记录日志,保留最长 24 小时。你通过 StreamViewType 选择每条记录携带的内容(仅键、新映像、旧映像,或新旧两者),然后借助 Lambda 触发器消费 stream,从而在不轮询的情况下对项变更做出反应。
- Streams 捕获项级变更,作为一份按时间排序、去重的日志,保留最长 24 小时。
- 你通过
StreamViewType选择每条记录携带什么:仅键、新映像、旧映像,或新旧两者。 - 记录在一个分区键内有序,且 stream 的分片方式与表相同。
- 原生消费者是 Lambda —— 一个对每批新记录运行一次的触发器,而 Kinesis Data Streams 则是 用于更丰富扇出的备选方案。
问题所在:不轮询也能反应
你需要“当一个 role.granted 事件被写入时告警我”。最朴素的做法是一个每分钟扫描新事件的计划
作业 —— 它每次都读取整个近期分区、消耗容量,且总是至少晚一分钟。
你真正想要的是一次推送:DynamoDB 在某个项变更的那一刻就告诉你。而这正是 Streams 所提供 的,把变更记录送到你的代码里,而不是让你去四处搜寻它。
Streams 如何工作
据 AWS 文档所述,DynamoDB Streams 存储“一份去重、按时间排序的变更日志,保留最长 24 小时”, 并原生集成 Lambda (DynamoDB 的变更数据捕获)。 每条记录描述一次项级修改。
当你启用一个 stream 时,你要选一个 StreamViewType,它控制每条记录携带变更后的项有多少
内容:
| StreamViewType | each record contains |
|---|---|
| KEYS_ONLY | only the key attributes of the changed item |
| NEW_IMAGE | the entire item as it looks after the change |
| OLD_IMAGE | the entire item as it looked before the change |
| NEW_AND_OLD_IMAGES | both the before and after images |
记录在每个分区键内有序,且 stream 沿着与表相同的分区结构分片。保留期为 24 小时 —— Streams 是一个反应缓冲区,而非永久历史。要保存持久的历史,你应存储事件本身(而这恰好正是 我们这张审计日志表的本质)。
原生消费者是一个 Lambda 触发器:DynamoDB 在新的 stream 记录到达时用一批它们来调用你的函数。
一个实战示例:对敏感审计事件告警
审计日志表配上一个 NEW_IMAGE 的 stream,于是每条记录都携带完整的新事件。一个 Lambda 消费
这一批,并只转发那些要紧的记录:
| stream record (NEW_IMAGE) | consumer action | ||
|---|---|---|---|
| TENANT#acme | EVENT#…#a2 | action=invoice.export | send to SIEM |
| TENANT#globex EVENT#…#b9 action=role.granted | page on-call | ||
| TENANT#acme | EVENT#…#a1 | action=login.success | ignore |
这个函数从不触碰表 —— 它纯粹对 stream 递给它的内容做出反应。无轮询、无扫描,且告警在写入后 数秒内触发。由于记录按分区键有序,一个租户的所有事件都会按它们被写入的顺序到达。
这也是维护一份下游副本的标准方式:一个 stream 消费者可以把每个事件投影进 OpenSearch 以 做全文审计搜索,或者聚合计数 —— 全都派生自同一份变更日志。
在 DynoTable 中操作
在你接上一个 stream 消费者之前,你需要知道你的 Lambda 将收到的项的确切结构 —— 存在哪些属性、
嵌套的映射和列表长什么样、一条 NEW_IMAGE 记录实际会包含什么。
要把一个样本项在纯 JSON 与 stream 记录所用的属性值结构之间相互转换,
DynamoDB JSON 转换器能在你的浏览器中完成。而在
DynoTable 中,你可以查看完整的项 — 包括它的 DynamoDB-JSON 形式 — 从而对照真实数据来建模
NEW_IMAGE 记录,而不是去猜字段结构。

如果你在本地测试一个消费者,就让表跑在 DynamoDB Local 上并以同样的方式检查它 —— 参见 连接到 DynamoDB Local。
坑与后续步骤
- 24 小时不是一个积压队列。 如果你的消费者停机一整天,记录会过期并消失。Streams 用于近乎 实时的反应,而非持久的回放 —— 历史请保存事件本身。
- 挑选你所需的最小
StreamViewType。NEW_AND_OLD_IMAGES会让载荷翻倍;如果你只需要键去 重新读取该项,KEYS_ONLY更便宜。 - 顺序是每个分区键内的,而非全局的。 两个不同租户的事件之间没有顺序保证 —— 只在一个租户 的分区之内才有。
- TTL 删除会作为 stream 记录出现,并带有系统属性标记,这正是你归档过期项的方式 —— 参见 DynamoDB TTL。
Streams 把审计日志变成了一个事件源。下一个运维方面的考量是一个项生命的另一端 —— 用 DynamoDB TTL 自动让旧事件过期。
下载 DynoTable,在你写下一行 Lambda 代码之前,检查你的 stream 消费者将收到的确切 项结构。


