亚马逊AWS官方博客

大规模 DynamoDB 表数据跨账号迁移指南

迁移方案背景介绍

在 DynamoDB 迁移中,对于单表数据量超过上 100G 的情况,数据导出和导入需要几十分钟甚至几个小时,这对停机窗口时间要求较短的迁移场景带来了很大的挑战,因此需要一种可以缩短 DynamoDB 迁移时间的方案。本方案基于此而来,采用全量+CDC(增量)方式进行,适用于大表在线迁移需求。

迁移方案架构图

全量阶段: 通过 DynamoDB table Export 将数据导出到目标 S3 存储桶中。然后在目标账号通过 DynamoDB Import from S3 将数据导入到目标 DynamoDB。

CDC 阶段: 通过在源表中开启 Stream(类似 Kafka 流数据),当有数据变更时触发 Lambda 函数将数据写入到目标 DynamoDB。

本质上,全量阶段并不会缩短时间,通过结合 CDC,可以将 DynamoDB 的迁移提前进行。只要保证在正式迁移的时间窗口里 CDC 阶段能将目标端与源端的数据追平,然后再进行割接即可。

迁移操作步骤

基础配置

源账号 AWS IAM User 权限配置(临时迁移用途的 AWS IAM User)

由于仅为迁移目的进行一次性授权,为了减少配置过程,本文章部分权限授予“FullAccess”,实际项目可根据不同要求进行最小化权限配置。

用户授权开启源表 PITR 权限,所需权限如下:AmazonDynamoDBFullAccess、AWSCloudFormationFullAccess、AWSLambda_FullAccess、IAMRoleLimitedAccess、S3LimitedAccess。其中 IAMRoleLimitedAccess,S3LimitedAccess 为自定义策略,对应 policy 如下:

IAMRoleLimitedAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:createRole",
                "iam:AttachRolePolicy",
                "iam:PutRolePolicy"
            ],
            "Resource": "*"
        }
    ]
}

S3LimitedAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:PutObjectAcl"
                
            ],
            "Resource": [
                "arn:aws:s3:::your-target-account-s3-bucket/*",
                "arn:aws:s3:::your-target-account-s3-bucket"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:CreateBucket",
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::aws-sam-cli-*/*",
                "arn:aws:s3:::aws-sam-cli-*"
            ]
        }
    ]
}

注:需要将上面 your-target-account-s3-bucket 替换真实的 s3 bucket。

开启源表 PITR 功能

使用被授权的源 IAM 用户为 DynamoDB 源表打开 PITR(下面的 demoTable 为示例表,正式配置需替换为真实的表名)

aws dynamodb update-continuous-backups \
--table-name demoTable \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true \

开启 DynamoDB 源表 Stream 功能

aws dynamodb update-table \
--table-name demoTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \

如下图所示:

这里需要记住 LatestStreamARN 值,在 CDC 过程需要。

配置目标 S3 桶策略

需要在目标账号的 S3 Bucket 权限里面设置存储桶策略,具体权限如下:

{
    "Version": "2012-10-17",
    "Id": "Policy1605099029795",
    "Statement": [
        {
            "Sid": "Stmt1605098975368",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<sourceaccountnumber>:user/<YourUser>"
            },
            "Action": [
                "s3:ListBucket",
                "s3:PutObjectAcl",
                "s3:AbortMultipartUpload",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3::: <nameofyourbucket>",
                "arn:aws:s3::: <nameofyourbucket>/*"
            ]
        }
    ]
}

全量同步

在源账户中将 DynamoDB 导出到目标 S3

aws dynamodb export-table-to-point-in-time \
--table-arn <source DynamoDB table arn> \
--s3-bucket <target s3 bucket name> \
--s3-bucket-owner <target aws account id> \

在目标账户 DynameDB Console 界面通过 Import From S3 功能将数据从 S3 还原到目标 DynameDB:


注: Source S3 URL 一定要选择到对应的 data 目录。

在上图的页面设置 Table name、 Partition key,保持和源表相同的配置即可,然后进行 import 。

CDC 同步

目标账号授权源账号对 DynamoDB 可写权限

在添加 permissions 时选择创建新的 policy


在 json 输入框填录以下 policy 代码,需要将 target-region、target-account、target-dynamodb-name 替换为真实的信息。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:PutItem",
                "dynamodb:DescribeTable",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:<target-region>:<target-account>:table/<target-dynamodb-name>"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "dynamodb:ListTables",
            "Resource": "*"
        }
    ]
}

在源账户启动 SAM 代码进行 CDC

1. 安装基础软件

sudo yum install git
wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
sha256sum aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
sudo ./sam-installation/install
sam --version
sudo amazon-linux-extras install python3.8

2. 下载 SAM 代码并执行

git clone https://github.com/aws-samples/cross-account-amazon-dynamodb-replication.git

cd cross-account-amazon-dynamodb-replication/ChangeDataCapture

vim template.yml #(作如下修改,将 79 行 false 改为 true)

3. 执行 SAM 代码(请确定用户拥有 SAM 执行权限)

sam build
sam deploy –guided

CDC 参数说明:

TargetDynamoDBTable: Target DynamoDB Table name
TargetAccountNumber: Target AWS Account Number
TargetRoleName: Target IAM Role name to be assumed by Lambda function
TargetRegion: The region for the target DynamoDB table
MaximumRecordAgeInSeconds: The maximum age (in seconds) of a record in the stream that Lambda sends to your function.
SourceTableStreamARN: Source DynamoDB table stream ARN

以上成功执行后就会自动进行源表到目标表的 CDC。

参考资料

https://thinkwithwp.com/blogs/database/cross-account-replication-with-amazon-dynamodb/

https://github.com/aws-samples/cross-account-amazon-dynamodb-replication#initial-load

本篇作者

黄家曦

亚马逊云科技解决方案架构师,负责基于亚马逊云科技云计算方案咨询和设计。曾就职于思科、中国电信,在网络以及运营商骨干网有丰富经验,热衷于大数据领域,熟悉 EMR、Kinesis、Athena、Glue 等数据分析服务与方案设计。

谭志强

亚马逊云科技迁移解决方案架构师,主要负责企业级客户的上云或跨云迁移工作,具有十几年 IT 专业服务经验,历任程序设计师、项目经理、技术顾问、解决方案架构师。