本文已参与「新人创作礼」活动,一起开启掘金创作之路。
二 、JDBC Source 插件
2.1 简介
通过Kafka Connect JDBC源连接器,您可以使用JDBC驱动程序将任何关系数据库中的数据导入ApacheKafka®主题。通过使用JDBC,此连接器可以支持各种数据库,而无需为每个数据库使用自定义代码。
通过定期执行SQL查询并为结果集中的每一行创建输出记录来加载数据。默认情况下,数据库中的所有表都被复制,每个表都复制到其自己的输出主题。监视数据库中的新表或删除表,并自动进行调整。从表复制数据时,连接器可以通过指定应使用哪些列来检测新数据或修改的数据来仅加载新行或修改的行。
您可以配置Java流应用程序以多种方式反序列化和摄取数据,包括Kafka控制台生产者,JDBC源连接器和Java客户端生产者。有关完整的代码示例,请参见connect-streams-pipeline。
2.2 环境准备
- Kafka和Schema Registry在默认端口上本地运行
- mysql可以远程访问
- 插件安装同上HDFS Sink安装方式
2.3 增量查询模式
每种增量查询模式都为每一行跟踪一组列,用于跟踪已处理的行以及哪些行是新的或已更新的行。该mode设置控制此行为,并支持以下选项:
- 递增列:包含每一行唯一ID的单个列,其中保证较新的行具有更大的ID,即一
AUTOINCREMENT列。请注意,此模式只能检测新行。无法检测到对现有行的更新,因此该模式仅应用于不可变数据。在数据仓库中流化事实表时,您可能会使用此模式的一个示例,因为这些表通常是仅插入的。递增列必须是整数类型。 - 时间戳列:在此模式下,包含修改时间戳的单个列用于跟踪上次处理数据的时间,并仅查询自该时间以来已被修改的行。请注意,由于时间戳不一定是唯一的,因此此模式不能保证所有更新的数据都将被传递:如果2行共享相同的时间戳并由增量查询返回,但是在崩溃前仅处理了一行,则第二次更新将被处理。系统恢复时未命中。
- 时间戳和递增列:这是最健壮和准确的模式,将递增列与时间戳列结合在一起。通过将两者结合起来,只要时间戳足够精细,每个(id,时间戳)元组将唯一地标识对行的更新。即使更新在部分完成后失败,系统恢复后仍可正确检测并交付未处理的更新。
- 自定义查询:源连接器支持使用自定义查询,而不是复制整个表。对于自定义查询,只要可以将必要
WHERE子句正确附加到查询中,就可以使用其他更新自动更新模式之一。或者,指定的查询可以自己处理对新更新的过滤。但是,请注意,将不会执行偏移量跟踪(与为每个记录记录incrementing和/或timestamp列值的自动模式不同 ),因此查询必须跟踪偏移量本身。 - 批量:此模式未过滤,因此根本不增量。它将在每次迭代时从表中加载所有行。如果要定期转储整个表,最终删除条目,下游系统可以安全地处理重复表,这将很有用。
请注意,使用某些列来检测更改的所有增量查询模式都将需要这些列上的索引才能有效地执行查询。
对于使用时间戳的增量查询模式,源连接器将使用一种配置 timestamp.delay.interval.ms来控制在将包含特定时间戳的行出现在结果中之前的等待时间。额外的等待时间可以使带有较早时间戳记的事务完成,并将相关的更改包括在结果中。有关更多信息,请参见配置属性。
2.4 Message Keys
Kafka消息是键/值对。对于JDBC连接器,值(有效负载)是要提取的表行的内容。但是,默认情况下,JBDC连接器不会生成密钥。
消息键对于设置分区策略很有用。密钥可以将消息定向到特定分区,并可以支持使用联接的下游处理。如果未使用消息密钥,则使用循环分发将消息发送到分区。
要为JBDC连接器设置消息密钥,请使用两个“单个消息转换”(SMT ):ValueToKey SMT和 ExtractField SMT。您将这两个SMT添加到JBDC连接器配置中。例如,以下内容显示了添加到配置的代码片段,该代码片段将表的id列accounts用作消息键。
curl -X POST http://localhost:8083/connectors -H "Content-Type: application/json" -d '{
"name": "jdbc_source_mysql_01",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"connection.url": "jdbc:mysql://mysql:3306/test",
"connection.user": "connect_user",
"connection.password": "connect_password",
"topic.prefix": "mysql-01-",
"poll.interval.ms" : 3600000,
"table.whitelist" : "test.accounts",
"mode":"bulk",
"transforms":"createKey,extractInt",
"transforms.createKey.type":"org.apache.kafka.connect.transforms.ValueToKey",
"transforms.createKey.fields":"id",
"transforms.extractInt.type":"org.apache.kafka.connect.transforms.ExtractField$Key",
"transforms.extractInt.field":"id"
}
}'
2.5 Mapping Column Types
源连接器具有一些选项,用于控制如何将列类型映射到“连接”字段类型。默认情况下,连接器将SQL / JDBC类型映射为Java中最精确的表示形式,这对于许多SQL类型而言很简单,但对于某些类型而言可能有点出乎意料。例如,SQL NUMERIC和DECIMAL类型具有由精度和小数位数控制的非常清晰的语义,最准确的表示形式是Decimal 使用Java 表示形式的Connect 逻辑类型BigDecimal。不幸的是,Avro将Decimal类型序列化为可能难以使用的原始字节。
源连接器的numeric.mapping配置将控制此映射。默认值为,none并且具有上述行为。
然而,该best_fit方案可能是大多数用户所期望的,因为它试图映射 NUMERIC列连接INT8,INT16,INT32,INT64,和FLOAT64 基于列的精度和刻度值:
| Precision | Scale | Connect “best fit” primitive type |
|---|---|---|
| 1 to 2 | -84 to 0 | INT8 |
| 3 to 4 | -84 to 0 | INT16 |
| 5 to 9 | -84 to 0 | INT32 |
| 10 to 18 | -84 to 0 | INT64 |
| 1 to 18 | positive | FLOAT64 |
该precision_only选项试图映射NUMERIC列连接INT8,INT16,INT32,和INT64仅基于列的精度,并在规模始终为0。
| Precision | Scale | Connect “best fit” primitive type |
|---|---|---|
| 1 to 2 | 0 | INT8 |
| 3 to 4 | 0 | INT16 |
| 5 to 9 | 0 | INT32 |
| 10 to 18 | 0 | INT64 |
NUMERIC列的精度和小数位数的任何其他组合将始终映射到Connect的Decimal类型。
注意
该numeric.precision.mapping属性较旧,现在已弃用。启用时,它完全等同于numeric.mapping=precision_only;启用时,它完全等同于numeric.mapping=none。
2.6 Configuration
源连接器使您可以灵活地从中导入数据的数据库以及如何导入数据的灵活性。本节首先介绍如何访问Confluent Platform不包含其驱动程序的数据库,然后给出一些涵盖常见场景的示例配置文件,然后提供可用配置选项的详尽描述。
完整的配置选项集在“ 配置属性”中列出,但是这里有一些模板配置,涵盖了一些常见的使用场景。
使用白名单将更改限制在MySQL数据库表的子集中,使用id和 modified所有白名单表上的标准列来检测已修改的行。此模式最可靠,因为它可以将唯一的,不可变的行ID与修改时间戳相结合,以确保即使在增量更新查询过程中过程终止,也不会丢失修改。
name=mysql-whitelist-timestamp-source
connector.class=io.confluent.connect.jdbc.JdbcSourceConnector
tasks.max=10
connection.url=jdbc:mysql://mysql.example.com:3306/my_database?user=alice&password=secret
table.whitelist=users,products,transactions
mode=timestamp+incrementing
timestamp.column.name=modified
incrementing.column.name=id
topic.prefix=mysql-
使用自定义查询而不是加载表,从而使您可以联接来自多个表的数据。只要查询不包括其自身的筛选,您仍可以将内置模式用于增量查询(在这种情况下,使用时间戳列)。请注意,这将您限制为每个连接器只有一个输出,并且由于没有表名,因此在这种情况下,主题“前缀”实际上是完整的主题名称。
name=mysql-whitelist-timestamp-source
connector.class=io.confluent.connect.jdbc.JdbcSourceConnector
tasks.max=10
connection.url=jdbc:postgresql://postgres.example.com/test_db?user=bob&password=secret&ssl=true
query=SELECT users.id, users.name, transactions.timestamp, transactions.user_id, transactions.payment FROM users JOIN transactions ON (users.id = transactions.user_id)
mode=timestamp
timestamp.column.name=timestamp
topic.prefix=mysql-joined-data