

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用自定义实施，跨账户复制 Amazon DynamoDB 表
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation"></a>

*Ramkumar Ramanujam，Amazon Web Services*

## Summary
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-summary"></a>

在Amazon Web Services (AWS) 上使用 Amazon DynamoDB 时，常见的用例是将开发、测试或模拟环境中的 DynamoDB 表与生产环境中的表数据进行复制或同步。标准做法是，在每个环境使用不同的 Amazon Web Services account。

DynamoDB 现在支持使用 AWS Backup 执行跨账户备份。有关使用 AWS Backup 时的相关存储成本信息，请参阅 [AWS Backup 定价](https://aws.amazon.com/backup/pricing/)。当您使用 AWS Backup 跨账户复制时，源账户和目标账户必须是 AWS Organizations 组织的组成部分。还有其他使用 AWS 服务的跨账户备份和还原解决方案，如 AWS Glue。但是，使用这些解决方案会增加应用程序占用空间，因为有更多的 Amazon Web Services 需要部署和维护。 

您也可使用 Amazon DynamoDB Streams 来捕获源账户中的表更改。然后，您可启动 AWS Lambda 函数，并在目标账户的目标表中进行相应的更改。但是从解决方案适用于源表和目标表必须始终保持同步的用例。它可能不适用于数据更新频率较高的开发、测试和模拟环境。

此模式提供了实施自定义解决方案，以将 Amazon DynamoDB 表从一个账户复制到另一个账户的步骤。这种模式可使用 C\$1、Java 和 Python 等常见编程语言来实现。我们建议使用 [AWS SDK](https://aws.amazon.com/tools/) 支持的语言。

## 先决条件和限制
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-prereqs"></a>

**先决条件**
+ 两个有效的 Amazon Web Services account 
+ 两个账户中的 DynamoDB 表
+ 了解 AWS Identity and Access Management (IAM) 角色和策略
+ 了解如何使用任何常用编程语言（例如 C\$1、Java 或 Python）访问 Amazon DynamoDB 表

**限制**

这种模式适用于大约 2 GB 或以内的 DynamoDB 表。通过额外的逻辑处理连接或会话中断、节流以及失败和重试，它可以用于更大的表。

从源表读取项目的 DynamoDB 扫描操作，在一次调用中最多只能获取 1 MB 的数据。对于大于 2 GB 的大表，此限制会增加执行完整表复制的总时间。

## 架构
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-architecture"></a>

下图显示了源和目标 AWS 账户之间的自定义实施。IAM 策略和安全令牌可与自定义实施一起使用。从源账户中的 Amazon DynamoDB 读取数据，然后将数据写入目标账户中的 DynamoDB。

![\[使用自定义实施进行复制的源和目标账户架构。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/ba8175be-9809-4c2e-b2d1-6b9180ed056c/images/d9d4c2c8-ff04-443f-9137-e37b8e23ccb5.png)


 

**自动化和扩展**

这种模式适用于较小（大约 2 GB）的 DynamoDB 表。 

若要将此模式应用于较大的表，请解决以下问题：
+ 在表复制操作期间，使用不同安全令牌维护两个活动会话。如表复制操作花费的时间超过令牌到期时间，则必须设置逻辑来刷新安全令牌。 
+ 如果未配置足够的读取容量单位 (RCUs) 和写入容量单位 (WCUs)，则源表或目标表的读取或写入可能会受到限制。请务必捕捉并处理异常情况。 
+ 处理任何其他失败或异常情况，并建立重试机制，以重试或从复制操作失败的地方继续操作。

## 工具
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-tools"></a>

**工具**
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) – Amazon DynamoDB 是一种全托管 NoSQL 数据库服务，提供快速而可预测的性能，能够实现无缝扩展。 
+ 所需其他工具将根据您为实现选择的编程语言而异。例如，如果你使用 C\$1，则需要微软 Visual Studio 和以下 NuGet 软件包：
  + `AWSSDK`
  + `AWSSDK.DynamoDBv2`

**代码**

以下 Python 代码段使用 Boto3 库，删除并重新创建 DynamoDB 表。

请勿使用 IAM 用户的 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`，因为这些都是长期凭证，在编程访问 Amazon Web Services 时应避免使用这些凭证。有关临时凭证的更多信息，请参阅*最佳实践*部分。

以下代码段中使用的 `AWS_ACCESS_KEY_ID` 、`AWS_SECRET_ACCESS_KEY` 和 `TEMPORARY_SESSION_TOKEN`，是从 AWS Security Token Service (AWS STS) 获取的临时凭证。

```
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.')
```

## 最佳实践
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-best-practices"></a>

**临时凭证**

作为安全最佳实践，在以编程方式访问 AWS 服务时，请避免使用 IAM 用户 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`，因为它们是长期凭证。请务必尝试使用临时凭证，以编程方式访问 Amazon Web Services。

例如，开发人员在开发过程中对应用程序中的 IAM 用户的 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 进行了硬编码，但在将更改推送至代码存储库之前，无法删除硬编码值。这些暴露的凭证可能被意外用户或恶意用户使用，这可能会产生严重影响（尤其是在暴露的凭证具有管理员权限的情况下）。应使用 IAM 控制台或 AWS 命令行界面（AWS CLI）立即停用或删除这些公开的凭证。

要获得以编程方式访问 Amazon Web Services 的临时凭证，请使用 AWS STS。临时凭证仅在指定时间内有效（从 15 分钟到 36 小时不等）。临时凭证允许的最长持续时间因角色设置和角色链接等因素而异。有关 AWS STS 的更多信息，请参阅[文档](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html)。

## 操作说明
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-epics"></a>

### 设置 DynamoDB 表
<a name="set-up-dynamodb-tables"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 DynamoDB 表。 | 在源和目标 Amazon Web Services account 中创建带索引的 DynamoDB 表。将容量配置设置为按需模式，这样 DynamoDB 就可以根据工作负载动态 read/write 扩展容量。 或者，您可以将预配置容量与 4000 RCUs 和 4000 配合使用。 WCUs | 应用程序开发人员，数据库管理员，迁移工程师 | 
| 填充源表格。 | 使用测试数据填充源账户的 DynamoDB 表。拥有至少 50 MB 或更多的测试数据有助于您查看表复制期间的峰值和平均 RCUs 消耗量。然后，您可根据需要更改容量配置。 | 应用程序开发人员，数据库管理员，迁移工程师 | 

### 设置用于访问 DynamoDB 表的凭证
<a name="set-up-credentials-to-access-the-dynamodb-tables"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 IAM 角色，以访问源表和目标 DynamoDB 表。 | 在源账户中创建 IAM 角色，该角色有权访问（读取）源账户中的 DynamoDB 表。将源账户添加至该角色的可信实体。在目标账户中创建一个 IAM 角色，该角色有权访问（创建、读取、更新、删除）目标账户中的 DynamoDB 表。 将目标账户添加至该角色的可信实体。 | AWS 应用程序开发人员 DevOps | 

### 将表数据从一个账户复制至另一个账户
<a name="copy-table-data-from-one-account-to-another"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 获取 IAM 角色的临时凭证。 | 获取在源账户中创建的 IAM 角色的临时凭证。获取在目标账户中创建的 IAM 角色的临时凭证。获取 IAM 角色临时凭证的一种方法是在 AWS CLI 中使用 AWS STS。<pre>aws sts assume-role --role-arn arn:aws:iam::<account-id>:role/<role-name> --role-session-name <session-name> --profile <profile-name></pre>使用相应的 AWS 配置文件（对应于源账户或目标账户）。有关获取临时凭证的不同方式的详细信息，请参阅以下内容：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation.html) | 应用程序开发人员、迁移工程师 | 
| 初始化 DynamoDB 客户端，以便访问源与目标 DynamoDB。 | 为源表和目标 DynamoDB 表初始化 AWS 开发工具包所提供的 DynamoDB 客户端。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation.html)有关使用 IAM 临时凭证发出请求的更多信息，请参阅 [AWS 文档](https://docs.aws.amazon.com/AmazonS3/latest/userguide/AuthUsingTempSessionToken.html)。 | 应用程序开发人员 | 
| 删除和重新创建目标表。 | 使用目标账户 DynamoDB 客户端，在目标账户中删除并重新创建目标 DynamoDB 表（以及索引）。从 DynamoDB 表中删除所有记录是一项代价高昂的操作，因为它会消耗预配置。 WCUs删除并重新创建表，可以避免这些额外费用。您可在创建表之后向其添加索引，但这会延长 2-5 分钟。通过将索引集传递至 `createTable` 调用，在创建表期间创建索引的效率更高。 | 应用程序开发人员 | 
| 执行表格复制。 | 重复以下步骤，直至复制完所有数据：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation.html)有关更多信息，请参阅*附件*部分中的 C\$1 参考实现（用于删除、创建和填充表）。还附上了示例表配置 JavaScript 对象表示法 (JSON) 文件。 | 应用程序开发人员 | 

## 相关资源
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-resources"></a>
+ [Amazon DynamoDB 文档](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html)
+ [在您的 Amazon Web Services account 中创建 IAM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html)
+ [AWS SDKs](https://aws.amazon.com/tools/)
+ [将临时凭证用于 AWS 资源](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)

## 附加信息
<a name="copy-amazon-dynamodb-tables-across-accounts-using-a-custom-implementation-additional"></a>

此模式是使用 C\$1 实现的，用于复制包含 200,000 个项目（平均项目大小为 5 KB，表大小为 250 MB）的 DynamoDB 表。目标 DynamoDB 表的预配置容量为 4000 和 4000。 RCUs WCUs

完整的表复制操作（从源账户到目标账户），包括删除和重新创建表，花了 5 分钟。消耗的总容量单位：30,000 个 RCUs 和大约 40 万个 WCUs。

有关 DynamoDB 容量模式的更多信息，请参阅 AWS 文档中的[读/写容量模式](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html)。

## 附件
<a name="attachments-ba8175be-9809-4c2e-b2d1-6b9180ed056c"></a>

要访问与此文档相关联的其他内容，请解压以下文件：[attachment.zip](samples/p-attach/ba8175be-9809-4c2e-b2d1-6b9180ed056c/attachments/attachment.zip)