DynamoDB Streams
DynamoDB Streams 是一份變更資料擷取(change-data-capture)記錄:表格上的每一次插入、更新與刪除,都會依序被擷取成一串你可以據以反應的記錄。這就是你把一張表格變成事件來源、而不必輪詢它的方法。
在稽核記錄的情境中,你希望在敏感事件落地的瞬間就做出反應 — 當有人匯出發票或授予管理員角色時觸發警示 — 而不必定時掃描表格。Streams 就是其中「推送」的那一側。
DynamoDB Streams 是如何運作的?
DynamoDB Streams 將表格上的每一次插入、更新與刪除,擷取為一份時間排序、去重的記錄,保留最長 24 小時。你透過 StreamViewType 選擇每筆記錄攜帶的內容(鍵、新影像、舊影像或兩者),再以 Lambda 觸發器消費 stream,即可在不輪詢的情況下對項目變更做出反應。
- Streams 擷取項目層級的變更,形成一份時間排序、去重的記錄,保留最長 24 小時。
- 你透過
StreamViewType選擇每筆記錄攜帶什麼:僅鍵、新影像、舊影像,或新舊兩者。 - 記錄在單一 partition key 內是有序的,而 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 |
記錄在每個 partition key 內是有序的,而 stream 沿著與表格相同的分割結構分片。保留期為 24 小時 — Streams 是一個反應緩衝區,而非永久歷史。若要持久的歷史,你就儲存事件本身(這正是我們的 audit-log 表格已經在做的事)。
原生的消費端是一個 Lambda 觸發器:DynamoDB 會在新的 stream 記錄抵達時,以一批記錄叫用你的函式。
一個實作範例:對敏感稽核事件發出警示
audit-log 表格設定了一個 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 交給它的內容做反應。沒有輪詢、沒有掃描,而警示在寫入後數秒內就觸發。因為記錄在每個 partition key 內是有序的,某個租戶的所有事件都會依其被寫入的順序抵達。
這也是維護下游副本的標準做法:一個 stream 消費端可以把每個事件投影到 OpenSearch 以進行全文稽核搜尋,或彙總計數 — 全都衍生自同一份變更記錄。
在 DynoTable 中實作
在你接上一個 stream 消費端之前,你需要知道 Lambda 將收到的項目的確切結構 — 有哪些屬性、巢狀的 map 與 list 長什麼樣、一筆 NEW_IMAGE 記錄實際會包含什麼。
若要在純 JSON 與 stream 記錄所用的屬性值結構之間轉換一個範例項目,DynamoDB JSON 轉換器 會在你的瀏覽器中完成。而在 DynoTable 中,你可以檢視完整的項目 — 包括它的 DynamoDB-JSON 形式 — 從而對著真實資料建模 NEW_IMAGE 記錄,而不必猜測欄位結構。

如果你在本機測試消費端,就對著 DynamoDB Local 執行該表格,並以相同方式檢視它 — 請見 連接 DynamoDB Local。
陷阱與後續步驟
- 24 小時不是待辦佇列。 若你的消費端停擺了一天,記錄就會逾時消失。Streams 用於近即時反應,而非持久重播 — 歷史請保留事件本身。
- 挑選你所需最小的
StreamViewType。NEW_AND_OLD_IMAGES會讓酬載加倍;若你只需要鍵以便回去重讀項目,KEYS_ONLY較便宜。 - 排序是每 partition key 的,不是全域的。 兩個不同租戶的事件之間沒有排序保證 — 只在單一租戶的分割之內才有。
- TTL 刪除會以 stream 記錄的形式出現,並帶有系統屬性標記,這就是你封存到期項目的方式 — 請見 DynamoDB TTL。
Streams 把稽核記錄變成一個事件來源。下一項維運考量是項目生命的另一端 — 用 DynamoDB TTL 自動讓舊事件到期。
下載 DynoTable 來檢視你的 stream 消費端將收到的確切項目結構,再動筆寫任何 Lambda 程式碼。


