使用自訂實作跨帳戶複製 Amazon DynamoDB 表格 - AWS 方案指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用自訂實作跨帳戶複製 Amazon DynamoDB 表格

創建者:拉姆庫瑪·拉馬努加姆 (AWS)

環境:生產

資料來源 Amazon DynamoDB

目標:Amazon DynamoDB

R 類型:不適用

工作負載:所有其他工作

技術:資料庫

AWS 服務:Amazon DynamoDB

Summary

在亞馬遜網路服務 (AWS) 上使用 Amazon DynamoDB 時,常見使用案例是使用生產環境中的表資料複製或同步處理開發、測試或暫存環境中的 DynamoDB 表。標準做法是,每個環境都使用不同的 AWS 帳戶。

DynamoDB 現在支援使用 AWS Backup 的跨帳戶備份。如需使用 AWS Backup 時相關儲存成本的相關資訊,請參閱 AWS Backup 定價。當您使用 AWS Backup 跨帳戶進行複製時,來源和目標帳戶必須是 AWS Organizations 組織的一部分。還有其他使用 AWS 服務 (例如 AWS Data Pipeline 或 AWS Glue) 的跨帳戶備份和還原解決方案。但是,使用這些解決方案會增加應用程式的佔用空間,因為需要部署和維護更多 AWS 服務。 

您也可以使用 Amazon DynamoDB 串流來擷取來源帳戶中的表格變更。然後,您可以啟動 AWS Lambda 函數,並在目標帳戶的目標資料表中進行相應的變更。但是該解決方案適用於必須始終保持同步源表和目標表的用例。它可能不適用於經常更新資料的開發、測試和測試環境。

此模式提供實作自訂解決方案的步驟,將 Amazon DynamoDB 表格從一個帳戶複製到另一個帳戶。這種模式可以使用常見的編程語言,如 C#,Java 和 Python 來實現。我們建議使用 AWS 開發套件支援的語言。

先決條件和限制

先決條件

  • 兩個作用中的 AWS 帳戶

  • 兩個帳戶中的 DynamoDB 表

  • AWS Identity and Access Management (IAM) 角色和政策的知識

  • 有關如何使用任何通用程式設計語言 (例如 C#、Java 或 Python) 存取亞馬遜動態資料表的知識

限制

此模式適用於大約 2 GB 或更小的 DynamoDB 表格。透過其他邏輯來處理連線或工作階段中斷、節流以及失敗和重試,可用於較大的資料表。

從來源資料表讀取項目的 DynamoDB 掃描作業只能在單一呼叫中擷取最多 1 MB 的資料。對於大於 2 GB 的大型資料表,此限制可能會增加執行完整表格複製的總時間。

架構

自動化和規模

此模式適用於大小較小 (約 2 GB) 的 DynamoDB 表格。 

若要將此模式套用至較大的資料表,請解決下列問題:

  • 在資料表複製作業期間,會使用不同的安全性權杖來維護兩個作用中工作階段。如果表複製操作花費的時間超過令牌到期時間,則必須設置邏輯才能刷新安全令牌。 

  • 如果未佈建足夠的讀取容量單位 (RCU) 和寫入容量單位 (WCU),則來源或目標資料表上的讀取或寫入可能會受到限制。一定要 catch 並處理這些異常。 

  • 處理任何其他失敗或例外狀況,並設置重試機制,以便從複製作業失敗的位置重試或繼續。

工具

工具

  • 亞馬遜 DynamoDB — Amazon DynamoDB 是全受管的 NoSQL 資料庫服務,可提供快速且可預測的效能以及無縫的可擴展性。 

  • 所需的其他工具會根據您為實作選擇的程式設計語言而有所不同。例如,如果您使用 C#,您將需要 Microsoft 視覺工作室和以下軟 NuGet 件包:

    • AWSSDK

    • AWSSDK.DynamoDBv2

Code

下列 Python 程式碼片段會使用 Boto3 程式庫刪除並重新建立 DynamoDB 資料表。

請勿使用 IAM 使用者AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID和,因為這些是長期登入資料,應避免以程式設計方式存取 AWS 服務。如需有關暫時登入資料的詳細資訊,請參閱最佳做法一節。

下列程式碼片段中TEMPORARY_SESSION_TOKEN使用的AWS_SECRET_ACCESS_KEY、和是從 AWS 安全性權杖服務 (AWS STS) 擷取的臨時登入資料。AWS_ACCESS_KEY_ID

import boto3 import sys import json #args = input-parameters = GLOBAL_SEC_INDEXES_JSON_COLLECTION, ATTRIBUTES_JSON_COLLECTION, TARGET_DYNAMODB_NAME, TARGET_REGION, ... #Input param: GLOBAL_SEC_INDEXES_JSON_COLLECTION #[{"IndexName":"Test-index","KeySchema":[{"AttributeName":"AppId","KeyType":"HASH"},{"AttributeName":"AppType","KeyType":"RANGE"}],"Projection":{"ProjectionType":"INCLUDE","NonKeyAttributes":["PK","SK","OwnerName","AppVersion"]}}] #Input param: ATTRIBUTES_JSON_COLLECTION #[{"AttributeName":"PK","AttributeType":"S"},{"AttributeName":"SK","AttributeType":"S"},{"AttributeName":"AppId","AttributeType":"S"},{"AttributeName":"AppType","AttributeType":"N"}] region = args['TARGET_REGION'] target_ddb_name = args['TARGET_DYNAMODB_NAME'] global_secondary_indexes = json.loads(args['GLOBAL_SEC_INDEXES_JSON_COLLECTION']) attribute_definitions = json.loads(args['ATTRIBUTES_JSON_COLLECTION']) # Drop and create target DynamoDB table dynamodb_client = boto3.Session(         aws_access_key_id=args['AWS_ACCESS_KEY_ID'],         aws_secret_access_key=args['AWS_SECRET_ACCESS_KEY'],         aws_session_token=args['TEMPORARY_SESSION_TOKEN'],     ).client('dynamodb')      # Delete table print('Deleting table: ' + target_ddb_name + ' ...') try: dynamodb_client.delete_table(TableName=target_ddb_name)     #Wait for table deletion to complete     waiter = dynamodb_client.get_waiter('table_not_exists')     waiter.wait(TableName=target_ddb_name)     print('Table deleted.') except dynamodb_client.exceptions.ResourceNotFoundException:     print('Table already deleted / does not exist.')     pass print('Creating table: ' + target_ddb_name + ' ...') table = dynamodb_client.create_table(     TableName=target_ddb_name,     KeySchema=[         {             'AttributeName': 'PK',             'KeyType': 'HASH'  # Partition key         },         {             'AttributeName': 'SK',             'KeyType': 'RANGE'  # Sort key         }     ],     AttributeDefinitions=attribute_definitions,     GlobalSecondaryIndexes=global_secondary_indexes,     BillingMode='PAY_PER_REQUEST' )      waiter = dynamodb_client.get_waiter('table_exists') waiter.wait(TableName=target_ddb_name)      print('Table created.')

最佳實務

臨時憑證

作為安全最佳實務,以程式設計方式存取 AWS 服務時,請避免使用 IAM 使用者AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID和,因為這些都是長期登入資料。一律嘗試使用臨時登入資料以程式設計方式存取 AWS 服務。

舉例來說,開發人員在開發期間對應用程式中 IAM 使用者AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID和進行硬式編碼,但在將變更推送至程式碼儲存庫之前,無法移除硬式編碼的值。這些暴露的認證可能會被非預期或惡意的用戶使用,這些用戶可能會產生嚴重影響(特別是當公開的憑據具有管理員權限時)。應使用 IAM 主控台或 AWS Command Line Interface (AWS CLI) (AWS CLI) 立即停用或刪除這些暴露的登入資料。

若要取得用於程式設計方式存取 AWS 服務的臨時登入資料,請使用 AWS STS。臨時身份證明僅在指定的時間內有效(從 15 分鐘到 36 小時)。允許的臨時證明資料持續時間上限會因角色設定和角色鏈結等因素而有所不同。如需 AWS STS 的詳細資訊,請參閱文件

史诗

任務描述所需技能

建立 DynamoDB 資料表。

在來源和目標 AWS 帳戶中建立具有索引的 DynamoDB 表格。

將容量佈建設定為隨需模式,這可讓 DynamoDB 根據工作負載動態擴展讀取/寫入容量。 

或者,您可以將佈建的容量與 4000 個 RCU 和 4000 個 WCU 搭配使用。

應用程式開發人員、DBA、移轉工程師

填入來源表格。

將測試資料填入來源帳戶中的 DynamoDB 表格。至少有 50 MB 或更多的測試資料可協助您查看表格複製期間使用的尖峰和平均 RCU。然後,您可以視需要變更容量佈建。

應用程式開發人員、DBA、移轉工程師
任務描述所需技能

建立 IAM 角色以存取來源和目標 DynamoDB 表格。

在來源帳戶中建立具有存取 (讀取) 來源帳戶中 DynamoDB 表格的權限的 IAM 角色。

將來源帳戶新增為此角色的信任實體。

在目標帳戶中建立 IAM 角色,具有存取 (建立、讀取、更新、刪除) 目標帳戶中 DynamoDB 表的權限。 

將目標帳戶新增為此角色的信任實體。

AWS 應用程式開發人員 DevOps
任務描述所需技能

取得 IAM 角色的臨時登入資料。

取得在來源帳戶中建立的 IAM 角色的臨時登入資料。

取得在目標帳戶中建立 IAM 角色的臨時登入資料。

取得 IAM 角色的臨時登入資料的一種方法是使用 AWS CLI 中的 AWS STS。

aws sts assume-role --role-arn arn:aws:iam::<account-id>:role/<role-name> --role-session-name <session-name> --profile <profile-name>

使用適當的 AWS 設定檔 (對應於來源或目標帳戶)。

如需取得暫時登入資料之不同方式的詳細資訊,請參閱下列內容:

應用程式開發人員、移轉

針對來源和目標 DynamoDB 存取,初始化 DynamoDB 用戶端。

針對來源和目標 DynamoDB 表格,初始化 AWS 開發套件所提供的 DynamoDB 用戶端。

  • 對於來源 DynamoDB 用戶端,請使用從來源帳戶擷取的臨時登入資料。

  • 對於目標 DynamoDB 用戶端,請使用從目標帳戶擷取的臨時登入資料。

如需使用 IAM 臨時登入資料提出請求的詳細資訊,請參閱 AWS 文件

應用程式開發人員

卸除並重新建立目標資料表。

使用目標帳戶 DynamoDB 用戶端,刪除並重新建立目標帳戶中的目標 DynamoDB 表格 (以及索引)。

從 DynamoDB 表中刪除所有記錄是一項昂貴的操作,因為它會消耗佈建的 WCU。刪除和重新創建表可避免這些額外費用。

您可以在建立表格之後將索引新增至表格,但這需要花費 2 到 5 分鐘的時間。透過將索引集合傳遞至createTable呼叫,在建立資料表期間建立索引會更有效率。

應用程式開發人員

執行表格複製。

重複以下步驟,直到複製所有資料為止:

  • 使用來源 DynamoDB 用戶端對來源帳戶中的表格執行掃描。每個 DynamoDB 掃描只會從表格擷取 1 MB 的資料,因此您必須重複此操作,直到讀取所有項目或記錄為止。

  • 對於每組掃描項目,請使用適用於 DynamoDB 的 AWS 開發套件中的BatchWriteItem呼叫,使用目標 DynamoDB 用戶端將項目寫入目標帳戶中的表格。這樣可以減少向 DynamoDB 發出的PutItem請求數量。 

  • BatchWriteItem寫入或置入的限制為 25 次,或者最多 16 MB。在呼叫之前,您必須新增邏輯,以 25 個計數累積掃描項目BatchWriteItemBatchWriteItem返回無法成功複製的項目列表。使用此清單,新增重試邏輯,以僅針對未成功的項目執行另一個BatchWriteItem呼叫。

如需詳細資訊,請參閱附件區段中 C# 中的參考實作 (用於卸除、建立和填入資料表)。還附加了示例表配置 JavaScript 對象符號(JSON)文件。

應用程式開發人員

相關資源

其他資訊

此模式是使用 C# 來複製含有 200,000 個項目的 DynamoDB 資料表 (平均項目大小為 5 KB,資料表大小為 250 MB) 來實作。目標 DynamoDB 料表已設定為具有 4000 個 RCU 和 4000 個 WCU 的佈建容量。

完整的資料表複製作業 (從來源帳戶到目標帳戶),包括卸除和重新建立資料表,都需要 5 分鐘。消耗的總容量單位:30,000 個 RCU 和約 40 萬個 WCU。

如需 DynamoDB 容量模式的詳細資訊,請參閱 AWS 文件中的讀取/寫入容量模式

附件

若要存取與此文件相關聯的其他內容,請解壓縮下列檔案:attachment.zip