使用自定义实施,跨账户复制 Amazon DynamoDB 表 - AWS Prescriptive Guidance

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

使用自定义实施,跨账户复制 Amazon DynamoDB 表

由 Ramkumar Ramanujam 创作 () AWS

环境:生产

来源:Amazon DynamoDB

目标:Amazon DynamoDB

R 类型:不适用

工作负载:所有其他工作负载

技术:数据库

AWS服务:亚马逊 DynamoDB

Summary

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

DynamoDB 现在支持使用 Backup 进行跨账户备份。AWS有关使用 AWS Backup 时的相关存储成本的信息,请参阅 Bac AWSkup 定价。当您使用 AWS Backup 跨账户复制时,源帐户和目标帐户必须是 Organization AWS s 组织的一部分。还有其他解决方案,可使用诸如 AWS Glue 之类的AWS服务进行跨账户备份和恢复。但是,使用这些解决方案会增加应用程序占用空间,因为需要部署和维护的AWS服务更多。 

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

此模式提供了实施自定义解决方案,以将 Amazon DynamoDB 表从一个账户复制到另一个账户的步骤。这种模式可使用 C#、Java 和 Python 等常见编程语言来实现。我们建议使用支持的语言AWSSDK

先决条件和限制

先决条件

  • 两个活跃AWS账户

  • 两个账户中的 DynamoDB 表

  • 对AWS身份和访问管理 (IAM) 角色和策略的了解

  • 了解如何使用任何常用编程语言(例如 C#、Java 或 Python)访问 Amazon DynamoDB 表

限制

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

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

架构

下图显示了源账户和目标AWS账户之间的自定义实现。IAM策略和安全令牌用于自定义实现。从源账户中的亚马逊 DynamoDB 读取数据,然后将数据写入目标账户中的 DynamoDB。

使用自定义实现进行复制的源账户和目标账户架构。

自动化和扩缩

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

若要将此模式应用于较大的表,请解决以下问题:

  • 在表复制操作期间,使用不同安全令牌维护两个活动会话。如表复制操作花费的时间超过令牌到期时间,则必须设置逻辑来刷新安全令牌。 

  • 如果未配置足够的读取容量单位 (RCUs) 和写入容量单位 (WCUs),则源表或目标表的读取或写入可能会受到限制。请务必捕捉并处理异常情况。 

  • 处理任何其他失败或异常情况,并建立重试机制,以重试或从复制操作失败的地方继续操作。

工具

工具

  • Amazon Dy namoDB — Amazon DynamoDB 是一项完全托管的SQL无数据库服务,可提供快速且可预测的性能以及无缝的可扩展性。 

  • 所需其他工具将根据您为实现选择的编程语言而异。例如,如果你使用 C#,则需要微软 Visual Studio 和以下 NuGet 软件包:

    • AWSSDK

    • AWSSDK.DynamoDBv2

代码

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

请勿使用IAM用户的AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY,因为这些都是长期凭证,对于以编程方式访问AWS服务,应避免使用这些证书。有关临时凭证的更多信息,请参阅最佳实践部分。

以下代码片段中TEMPORARY_SESSION_TOKEN使用的AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY、和是从AWS安全令牌服务 () 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.')

最佳实践

临时凭证

作为安全最佳实践,在以编程方式访问AWS服务时,请避免使用IAM用户的AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY,因为这些都是长期凭证。请务必尝试使用临时凭证以编程方式访问AWS服务。

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

要获取以编程方式访问AWS服务的临时证书,请使用AWSSTS。临时凭证仅在指定时间内有效(从 15 分钟到 36 小时不等)。临时凭证允许的最长持续时间因角色设置和角色链接等因素而异。有关的更多信息 AWSSTS,请参阅文档

操作说明

任务描述所需技能

创建 DynamoDB 表。

在源账户和目标账户中创建带有索引的 DynamoDB 表。AWS

将容量配置设置为按需模式,如此 DynamoDB 就可以根据工作负载动态扩展读/写容量。 

或者,您可以将预配置容量与 4000 RCUs 和 4000 配合使用。WCUs

应用程序开发人员DBA、迁移工程师

填充源表格。

使用测试数据填充源账户的 DynamoDB 表。拥有至少 50 MB 或更多的测试数据有助于您查看表复制期间的峰值和平均RCUs消耗量。然后,您可根据需要更改容量配置。

应用程序开发人员DBA、迁移工程师
任务描述所需技能

创建IAM角色以访问源表和目标 DynamoDB 表。

在源账户中创建一个有权访问(读取)源账户中的 DynamoDB 表的IAM角色。

将源账户添加至该角色的可信实体。

在目标账户中创建一个有权访问(创建、读取、更新、删除)目标账户中的 DynamoDB 表的IAM角色。 

将目标账户添加至该角色的可信实体。

应用程序开发者,AWS DevOps
任务描述所需技能

获取IAM角色的临时证书。

获取在源账户中创建的IAM角色的临时证书。

获取在目标账户中创建的IAM角色的临时证书。

获取IAM角色临时证书的一种方法是AWSSTS从中使用AWSCLI。

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 表初始化由AWSSDK提供的 DynamoDB 客户端。

  • 对于源 DynamoDB 客户端,请使用从源账户获取的临时凭证。

  • 对于目标 DynamoDB 客户端,请使用从目标账户获取的临时凭证。

有关使用IAM临时证书发出请求的更多信息,请参阅AWS文档

应用程序开发人员

删除和重新创建目标表。

使用目标账户 DynamoDB 客户端,在目标账户中删除并重新创建目标 DynamoDB 表(以及索引)。

从 DynamoDB 表中删除所有记录是一项代价高昂的操作,因为它会消耗预配置。WCUs删除并重新创建表,可以避免这些额外费用。

您可在创建表之后向其添加索引,但这会延长 2-5 分钟。通过将索引集传递至 createTable 调用,在创建表期间创建索引的效率更高。

应用程序开发人员

执行表格复制。

重复以下步骤,直至复制完所有数据:

  • 使用源 DynamoDB 客户端对源账户的表执行扫描。每次 DynamoDB 扫描仅从表中检索 1 MB 数据,因此您必须重复此操作,直到读取所有项目或记录。

  • 对于每组扫描的项目,使用对 DynamoDB 的调用,使用目标 DynamoDB 客户端将项目写入目标账户BatchWriteItem中的AWSSDK表。这将减少向 DynamoDB 发出的 PutItem 请求的数量。 

  • BatchWriteItem 限制为 25 次写入或放置,或最多 16 MB。在调用 BatchWriteItem 前,您必须添加逻辑以累积已扫描的项目,计数为 2。BatchWriteItem 返回无法成功复制的项目列表。使用此列表,添加重试逻辑,以便仅使用未成功的项目执行另一次 BatchWriteItem 调用。

有关更多信息,请参阅附件部分中的 C# 参考实现(用于删除、创建和填充表)。还附上了示例表配置 JavaScript 对象表示法 (JSON) 文件。

应用程序开发人员

相关资源

其他信息

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

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

有关 DynamoDB 容量模式的更多信息,请参阅文档中的读/写容量模式。AWS

附件

要访问与此文档相关联的其他内容,请解压以下文件:attachment.zip