DynamoDB Streams 完整指南(含範例)
DynamoDB Streams 是一個變更資料擷取(change-data-capture)日誌:一個表格上的 每一次插入、更新和刪除,都會被有序地擷取成一串你可以據以反應的記錄。 它是你不必輪詢一個表格就能把它變成一個事件來源的方法。
在那個稽核日誌的情境裡,你想在一個敏感事件落地的那一刻就反應 — 在有人匯出一張發票或授予一個管理員角色時觸發一個警報 — 而不必 定時掃描表格。Streams 就是那件事的推送端。
DynamoDB Streams 是怎麼運作的?
DynamoDB Streams 把一個表格上的每一次插入、更新和刪除,擷取成一個按時間排序、去重的記錄日誌,保留最長達 24 小時。你用 StreamViewType(鍵、新影像、舊影像,或兩者)選擇每一筆記錄攜帶什麼,然後用一個 Lambda 觸發器消費這個串流,不必輪詢就能對項目變更做出反應。
- Streams 把項目層級的變更擷取成一個按時間排序、去重的日誌, 保留最長達 24 小時。
- 你選擇每一筆記錄攜帶什麼,透過
StreamViewType:只有鍵、新 影像、舊影像,或舊與新兩者。 - 記錄是每個項目有序的 — 對一個項目的變更會以它們被寫入的順序 抵達 — 而一個串流會沿著和 相同的方式分片。
- 原生的消費者是 Lambda — 一個對每一批新記錄執行的觸發器, 而 Kinesis Data Streams 則是需要更豐富扇出時的替代方案。
問題所在:不輪詢就反應
你需要「在一個 role.granted 事件被寫入時提醒我」。天真的做法是
一個每分鐘掃描新事件的排程工作 — 這每次都會讀取整個近期
partition、花費容量,而且永遠至少晚一分鐘。
你真正想要的是一個推送:DynamoDB 在一個項目變更的那一刻告訴 你。那正是 Streams 所提供的,變更記錄會被送到你的程式碼裡,而不是 你去追它。
Streams 如何運作
按照 AWS 的文件,DynamoDB Streams 為變更保留一個去重、按時間 排序的日誌,最長達 24 小時,並有原生的 Lambda 整合 (DynamoDB 的變更資料擷取)。 每一筆記錄描述一次項目層級的修改。
當你啟用一個串流時,你挑一個 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 結構分片。保留時間 是 24 小時 — Streams 是一個反應緩衝區,不是一份永久的歷史。要有 耐久的歷史,你就儲存那些事件本身(那正是我們的稽核日誌表格 本來就是的東西)。
原生的消費者是一個 Lambda 觸發器:DynamoDB 在新的串流記錄 抵達時,用一批它們來呼叫你的函數。
一個實作範例:對敏感的稽核事件發警報
稽核日誌表格獲得一個帶 NEW_IMAGE 的串流,所以每一筆記錄攜帶
完整的新事件。一個 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 |
這個函數從不碰觸表格 — 它純粹對串流交給它的東西做出反應。 沒有輪詢、沒有掃描,而且警報在寫入後幾秒內就觸發。串流 記錄是每個項目有序的,所以對同一個事件項目的接連變更會以 它們被寫入的順序抵達。
這也是維護一份下游副本的標準做法:一個串流 消費者可以把每一個事件投影進 OpenSearch 以做全文稽核搜尋,或 聚合計數 — 全都衍生自同一份變更日誌。
在 DynoTable 中操作
在你接上一個串流消費者之前,你需要知道你的 Lambda 將收到的
項目的確切樣貌 — 哪些屬性存在、巢狀的 map 和 list 長什麼樣、
一個 NEW_IMAGE 記錄實際會包含什麼。
要在純 JSON 和一個串流記錄所用的 attribute-value 樣貌之間轉換一個
樣本項目,DynamoDB JSON 轉換器 會在你的
瀏覽器裡完成。而在 DynoTable 裡,你可以檢視完整的項目 — 包括它的
DynamoDB-JSON 形式 — 這樣你就對著真實資料為 NEW_IMAGE 記錄建模,
而不是猜測欄位樣貌。

如果你在本地測試一個消費者,就對著 DynamoDB Local 執行這個表格並 以同樣的方式檢視它 — 見 連接到 DynamoDB Local。
陷阱與後續步驟
- 24 小時不是一個積壓佇列。 如果你的消費者停擺一天,記錄 就會老化並消失。Streams 是為了接近即時的反應,而非耐久的重播 — 歷史請保留那些事件本身。
- 挑你需要的最小
StreamViewType。NEW_AND_OLD_IMAGES會讓 酬載加倍;如果你只需要那個鍵去重讀項目,KEYS_ONLY更便宜。 - 順序是每個項目的,不是每個 partition key 或全域的。 DynamoDB 只 對同一個項目的接連變更保證順序;跨不同項目之間沒有順序保證, 即使在同一個 partition key 內也是如此。
- TTL 刪除會以串流記錄的形式出現,帶著那個系統屬性標記,這 就是你歸檔到期項目的方法 — 見 DynamoDB TTL。
Streams 把稽核日誌變成一個事件來源。下一個操作上的顧慮是一個 項目生命週期的另一端 — 用 DynamoDB TTL 自動 讓舊事件到期。
下載 DynoTable,在你寫下一行 Lambda 程式碼之前,先 檢視你的串流消費者將收到的確切項目樣貌。


