MySQL到DynamoDB:使用Kafka在AWS上建立一个流数据管线
使用MSK Connect的变化数据捕获,在Aurora MySQL和DynamoDB之间同步数据。
这一部分将展示变化数据捕获的操作,让你跟踪数据库表中的行级变化,以响应创建、更新和删除操作。例如,在MySQL中,这些变化数据事件是通过MySQL二进制日志(binlog)暴露的。
在第一部分中,我们在数据管道的源部分使用了Datagen连接器--它帮助我们为MSK主题生成模拟数据,并使事情变得简单。我们将使用Aurora MySQL作为数据源,并利用它的变化数据捕获功能与Debezium的MySQL连接器,从Aurora MySQL的表中实时提取数据,推送到MSK主题。然后,我们将继续使用DynamoDB水槽连接器,就像我们之前做的那样。
如果你是Debezium的新手...
它是一个分布式平台,建立在不同数据库中可用的变更数据捕获功能之上。它提供了一套Kafka Connect连接器,可以挖掘数据库表中的行级变化(使用CDC),并将其转换为事件流。这些被发送到Kafka,并可以提供给所有下游的应用程序。
下面是这篇博文中提出的解决方案的高级图表。
我假设你是从第一部分开始关注的,第一部分已经涵盖了本教程所需的基本基础设施和服务的创建过程。如果你还没有,请参考第一部分中的准备基础设施组件和服务部分
数据管道第1部分:Aurora MySQL到MSK
让我们开始创建管道的前半部分,将数据从Aurora MySQL表中同步到MSK中的主题。
在本节中,你将:
- 下载Debezium连接器工件
- 在MSK中创建自定义插件
- 将Debezium源连接器部署到MSK连接中
最后,你将拥有数据管道的前半部分,可以开始使用了!
创建一个自定义插件和连接器
将Debezium连接器上传到Amazon S3
登录Kafka客户端EC2实例,运行这些命令。
Shell
sudo -u ec2-user -i
mkdir debezium && cd debezium
wget https://repo1.maven.org/maven2/io/debezium/debezium-connector-mysql/1.9.0.Final/debezium-connector-mysql-1.9.0.Final-plugin.tar.gz
tar xzf debezium-connector-mysql-1.9.0.Final-plugin.tar.gz
cd debezium-connector-mysql
zip -9 ../debezium-connector-mysql-1.9.0.Final-plugin.zip *
cd ..
aws s3 cp ./debezium-connector-mysql-1.9.0.Final-plugin.zip s3://msk-lab-<ENTER_YOUR_AWS_ACCOUNT_ID>-plugins-bucket/
创建自定义插件
关于如何创建MSK连接插件的步骤说明,请参阅官方文档中的使用AWS管理控制台创建自定义插件。
在创建自定义插件时,确保选择你在上一步上传到S3
的Debezium连接器压缩文件。
创建Debezium源连接器
关于如何创建MSK Connect连接器的分步说明,请参考官方文档中的创建连接器。
要创建一个连接器:
- 选择你刚刚创建的插件。
- 输入连接器名称并选择MSK集群以及IAM认证
- 你可以在连接器配置部分输入下面提供的内容。请确保你根据你的设置替换以下配置。
database.history.kafka.bootstrap.servers
- 输入MSK集群的端点database.hostname
- 输入Aurora RDS MySQL端点
其余的配置不做改变
YAML
connector.class=io.debezium.connector.mysql.MySqlConnector
database.user=master
database.server.id=123456
tasks.max=1
database.history.kafka.topic=dbhistory.salesdb
database.history.kafka.bootstrap.servers=<ENTER MSK CLUSTER ENDPOINT>
database.server.name=salesdb
database.port=3306
include.schema.changes=true
database.hostname=<ENTER RDS MySQL ENDPOINT>
database.password=S3cretPwd99
database.include.list=salesdb
value.converter.schemas.enable=false
key.converter.schemas.enable=false
key.converter=org.apache.kafka.connect.storage.StringConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
database.history.consumer.security.protocol=SASL_SSL
database.history.consumer.sasl.mechanism=AWS_MSK_IAM
database.history.consumer.sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
database.history.consumer.sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler
database.history.producer.security.protocol=SASL_SSL
database.history.producer.sasl.mechanism=AWS_MSK_IAM
database.history.producer.sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
database.history.producer.sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler
transforms=unwrap
transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState
- 在访问权限下,为连接器选择正确的IAM角色(名称中含有
AuroraConnectorIAMRole
)。 - 点击 "下一步"移动到安全选项--保持不变
- 点击下一步。对于日志交付,选择交付给Amazon CloudWatch Logs。找到并选择
/msk-connect-demo-cwlog-group
- 点击下一步- 在最后一页,向下滚动并点击创建连接器以启动该过程,并等待连接器启动。
一旦完成,并且连接器已经过渡到运行状态,继续进行下面的步骤。
测试管道
我们要确认salesdb
数据库中的SALES_ORDER
表的记录是否已被推送到MSK主题中。要做到这一点,从EC2主机,运行Kafka CLI消费者。
注意主题名称
salesdb.salesdb.SALES_ORDER
- 这是按Debezium的惯例。
外壳
sudo -u ec2-user -i
export MSK_BOOTSTRAP_ADDRESS=<ENTER MSK CLUSTER ENDPOINT>
/home/ec2-user/kafka/bin/kafka-console-consumer.sh --bootstrap-server $MSK_BOOTSTRAP_ADDRESS --consumer.config /home/ec2-user/kafka/config/client-config.properties --from-beginning --topic salesdb.salesdb.SALES_ORDER | jq --color-output .
在另一个终端,使用MySQL客户端,连接到Aurora数据库并插入一些记录。
MySQL
sudo -u ec2-user -i
export RDS_AURORA_ENDPOINT=<ENTER RDS MySQL ENDPOINT>
mysql -f -u master -h $RDS_AURORA_ENDPOINT --password=S3cretPwd99
USE salesdb;
select * from SALES_ORDER limit 5;
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29001, 2568, now(), 'STANDARD');
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29002, 1649, now(), 'ONE-DAY');
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29003, 3861, now(), 'TWO-DAY');
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29004, 2568, now(), 'STANDARD');
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29005, 1649, now(), 'ONE-DAY');
INSERT INTO SALES_ORDER (ORDER_ID, SITE_ID, ORDER_DATE, SHIP_MODE) VALUES (29006, 3861, now(), 'TWO-DAY');
如果一切设置正确,你应该在消费者终端看到这些记录。
JSON
{
"ORDER_ID": 29001,
"SITE_ID": 2568,
"ORDER_DATE": 1655279536000,
"SHIP_MODE": "STANDARD"
}
{
"ORDER_ID": 29002,
"SITE_ID": 1649,
"ORDER_DATE": 1655279536000,
"SHIP_MODE": "ONE-DAY"
}
{
"ORDER_ID": 29003,
"SITE_ID": 3861,
"ORDER_DATE": 1655279563000,
"SHIP_MODE": "TWO-DAY"
}
...
紧凑的变更事件有效载荷的秘密
注意到变化数据捕获事件的有效载荷是多么紧凑。这是因为我们将连接器配置为使用io.debezium.transforms.ExtractNewRecordState
,这是一个Kafka单一消息转换(SMT)。默认情况下,Debezium变更事件的结构是相当复杂的--与变更事件一起,它还包括元数据,如模式、源数据库信息等。它看起来像这样。
壳
{
"before": null,
"after": {
"ORDER_ID": 29003,
"SITE_ID": 3861,
"ORDER_DATE": 1655279563000,
"SHIP_MODE": "TWO-DAY"
},
"source": {
"version": "1.9.0.Final",
"connector": "mysql",
"name": "salesdb",
"ts_ms": 1634569283000,
"snapshot": "false",
"db": "salesdb",
"sequence": null,
"table": "SALES_ORDER",
"server_id": 1733046080,
"gtid": null,
"file": "mysql-bin-changelog.000003",
"pos": 43275145,
"row": 0,
"thread": null,
"query": null
},
"op": "c",
"ts_ms": 1655279563000,
"transaction": null
...
由于Kafka SMT(使用transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState
指定),我们可以有效地flatten
事件的有效载荷,并根据我们的要求进行定制。
数据管道第2部分:MSK到DynamoDB
现在我们可以把注意力转移到管道的后半部分,它负责在DynamoDB Sink连接器的帮助下将数据从MSK主题带到DynamoDB表中。
如果DynamoDB表不存在,连接器会自动为你创建一个表,但它使用默认设置,即它在供应模式下创建一个表,有10
读取容量单位(RCUs)和10
写入容量单位(WCUs)。
但是,你的用例可能需要一个配置。例如,为了处理大量的数据,你可能想配置自动扩展,或者甚至更好的是,为你的表激活按需模式。
这正是我们要做的。
在你继续之前,创建一个DynamoDB表
使用以下设置。
- 表名 -
kafka_salesdb.salesdb.SALES_ORDER
(不要改变表名) - 分区键 -
ORDER_ID
(数字) - 范围键 -
SITE_ID
(Number) - 容量模式 - 随需应变
就这样,你就可以开始了!
创建一个自定义插件和连接器
关于如何创建MSK连接插件的步骤说明,请参考官方文档中的使用AWS管理控制台创建自定义插件。
在创建自定义插件时,确保选择你在上一步上传至S3
的DynamoDB连接器压缩文件。
关于如何创建MSK Connect连接器的步骤说明,请参阅官方文档中的创建连接器。
要创建一个连接器:
- 选择你刚刚创建的插件。
- 输入连接器名称并选择MSK集群以及IAM认证
- 你可以在连接器配置部分输入下面提供的内容。请确保你根据你的设置替换以下配置。
- 为
topics
属性使用正确的主题名称(本例中我们使用salesdb.salesdb.SALES_ORDER
,因为这是Debezium源连接器采用的主题名称格式)。 - 对于
confluent.topic.bootstrap.servers
,输入MSK集群端点。 - 对于
aws.dynamodb.endpoint
和aws.dynamodb.region
,输入你创建DynamoDB表的区域,例如us-east-1
其余的配置不做改变
YAML
connector.class=io.confluent.connect.aws.dynamodb.DynamoDbSinkConnector
tasks.max=2
aws.dynamodb.region=<ENTER AWS REGION e.g. us-east-1>
aws.dynamodb.endpoint=https://dynamodb.<ENTER AWS REGION>.amazonaws.com
topics=salesdb.salesdb.SALES_ORDER
value.converter.schemas.enable=false
key.converter=org.apache.kafka.connect.storage.StringConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
table.name.format=kafka_${topic}
confluent.topic.bootstrap.servers=<ENTER MSK CLUSTER ENDPOINT>
confluent.topic.security.protocol=SASL_SSL
confluent.topic.sasl.mechanism=AWS_MSK_IAM
confluent.topic.sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
confluent.topic.sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler
aws.dynamodb.pk.hash=value.ORDER_ID
aws.dynamodb.pk.sort=value.SITE_ID
- 在访问权限下,为连接器选择正确的IAM角色(名称中含有
DynamoDBConnectorIAMRole
)。 - 点击 "下一步",进入安全选项--保持不变
- 点击下一步。对于日志交付,选择Deliver to Amazon CloudWatch Logs。找到并选择
/msk-connect-demo-cwlog-group
- 点击 "下一步" - 在最后一页,向下滚动并点击 "创建连接器"以启动该过程,并等待连接器的启动。
一旦完成,连接器已经过渡到运行状态,就可以继续下面的步骤。
选择DynamoDB的主键
在上面的配置中,我们将aws.dynamodb.pk.hash
和aws.dynamodb.pk.sort
分别设置为value.ORDER_ID
和value.SITE_ID
。这意味着Kafka主题事件有效载荷中的ORDER_ID
字段将被用作分区键,而SITE_ID
的值将被指定为范围键(根据你的要求,你也可以让aws.dynamodb.pk.sort
为空)。
测试端到端管道
作为初始加载过程的一部分,连接器确保所有来自Kafka主题的现有记录被持久化在连接器配置中指定的DynamoDB表中。在这种情况下,你应该在DynamoDB中看到超过29000
的记录(根据SALES_ORDER
表),你可以运行查询来探索数据。
为了继续测试端到端管道,你可以在SALES_ORDER
表中插入更多的数据,并确认它们通过Debezium源连接器同步到Kafka,并一直到DynamoDB,这要感谢水槽连接器。
删除资源
一旦你完成了,删除你创建的资源:
- 删除S3桶的内容 (
msk-lab-<YOUR ACCOUNT_ID>-plugins-bucket
) - 删除CloudFormation栈
- 删除DynamoDB表
- 删除MSK Connect连接器、插件和自定义配置
变更数据捕获是一个强大的工具,但我们需要一种方法来挖掘这些事件日志,并使它们对其他依赖这些数据的服务可用。在这一部分中,你看到了我们如何利用这一能力,使用Kafka Connect在MySQL和DynamoDB之间建立一个流式数据管道。
这个系列就这样结束了。构建愉快!