MySQL到DynamoDB:使用Kafka在AWS上建立一个流数据管道

190 阅读8分钟

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连接器的分步说明,请参考官方文档中的创建连接器

要创建一个连接器:

  1. 选择你刚刚创建的插件。
  2. 输入连接器名称并选择MSK集群以及IAM认证
  3. 你可以在连接器配置部分输入下面提供的内容。请确保你根据你的设置替换以下配置。
  • 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
  1. 访问权限下,为连接器选择正确的IAM角色(名称中含有AuroraConnectorIAMRole )。
  2. 点击 "下一步"移动到安全选项--保持不变
  3. 点击下一步。对于日志交付,选择交付给Amazon CloudWatch Logs。找到并选择/msk-connect-demo-cwlog-group
  4. 点击下一步- 在最后一页,向下滚动并点击创建连接器以启动该过程,并等待连接器启动。

一旦完成,并且连接器已经过渡到运行状态,继续进行下面的步骤。

测试管道

我们要确认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连接器的步骤说明,请参阅官方文档中的创建连接器

要创建一个连接器:

  1. 选择你刚刚创建的插件。
  2. 输入连接器名称并选择MSK集群以及IAM认证
  3. 你可以在连接器配置部分输入下面提供的内容。请确保你根据你的设置替换以下配置。
  • topics 属性使用正确的主题名称(本例中我们使用salesdb.salesdb.SALES_ORDER ,因为这是Debezium源连接器采用的主题名称格式)。
  • 对于confluent.topic.bootstrap.servers ,输入MSK集群端点。
  • 对于aws.dynamodb.endpointaws.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
  1. 访问权限下,为连接器选择正确的IAM角色(名称中含有DynamoDBConnectorIAMRole )。
  2. 点击 "下一步",进入安全选项--保持不变
  3. 点击下一步。对于日志交付,选择Deliver to Amazon CloudWatch Logs。找到并选择/msk-connect-demo-cwlog-group
  4. 点击 "下一步" - 在最后一页,向下滚动并点击 "创建连接器"以启动该过程,并等待连接器的启动。

一旦完成,连接器已经过渡到运行状态,就可以继续下面的步骤。

选择DynamoDB的主键

在上面的配置中,我们将aws.dynamodb.pk.hashaws.dynamodb.pk.sort 分别设置为value.ORDER_IDvalue.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之间建立一个流式数据管道。

这个系列就这样结束了。构建愉快!