本文档主要是对JDBC Source、Sink与HDFS Sink插件相关文档的介绍以及简单的demo示例。对应的HDFS3 版本、HDFS2 Source 版本官方没有开源需要授权后使用(试用期30天),本文档暂不涉及。对HDFS3-Sink组件相关文档的整理过程中与到组件内部目前存在bug需要待修复,可以把数据存储到HDFS,但是在自动创建Hive的外部表时无法获取到对应的MetaStore的元数据信息,导致创建失败。经过测试HDFS2-Sink目前满足数据到Hadoop3 集群存储数据以及自动创建Hive的外部表。**HDFS-Sink的替代方案目前可以使用HDFS2-Sink版本。**针对HDFS2-Sink目前针对相关业务存储bug,内部实现是依靠flush.size来刷新文件的,当写入的条数不足时将不会刷新导致数据丢失(需要针对特定版本进行完善)。JDBC在本次的测试整理中未发现问题。
通过Kafka Connect HDFS 2连接器,您可以将多种格式的数据从Kafka主题导出到HDFS 3.x文件,并与Hive集成以使数据立即可用于通过HiveQL查询。
连接器会定期轮询来自ApacheKafka®的数据,并将其写入HDFS。来自每个Kafka主题的数据由提供的分区程序进行分区,并分为多个块。每个数据块都表示为一个HDFS文件,其中包含主题,Kafka分区,该数据块在文件名中的开始和结束偏移量。如果未在配置中指定分区程序,则使用保留Kafka分区的默认分区程序。每个数据块的大小取决于写入HDFS的记录数,写入HDFS的时间以及架构兼容性。
HDFS连接器与Hive集成在一起,启用后,该连接器会自动为每个Kafka主题创建一个外部Hive分区表,并根据HDFS中的可用数据更新该表。
完全一次交付:连接器使用预写日志来确保每个记录仅一次导出到HDFS。另外,连接器通过将Kafka偏移信息编码到文件中来管理偏移提交,以便我们可以从最后提交的偏移开始,以防失败和任务重新启动。
可扩展的数据格式:该连接器开箱即用,支持以Avro和Parquet格式将数据写入HDFS。另外,您可以通过扩展Format
类将其他格式写入HDFS 。
Hive集成:连接器开箱即用地支持Hive集成,启用后,连接器会为导出到HDFS的每个主题自动创建Hive外部分区表。
安全HDFS和Hive Metastore支持:连接器支持Kerberos身份验证,因此可与安全HDFS和Hive Metastore一起使用。
可插拔分区程序:该连接器支持默认分区程序,字段分区程序和基于时间的分区程序,包括开箱即用的每日和每小时分区程序。您可以通过扩展Partitioner
类来实现自己的分区程序。另外,您可以通过扩展TimeBasedPartitioner
类来自定义基于时间的分区程序。
**模式演变:**仅当使用默认命名策略()生成记录时,模式演变才起作用TopicNameStrategy
。如果使用其他命名策略,则可能会发生错误。这是因为记录彼此不兼容。如果使用其他命名策略,schema.compatibility
则应设置为NONE
。这可能会导致目标文件较小,因为每次模式ID在记录之间更改时,接收器连接器都会创建一个新文件。有关命名策略的更多信息,请参见主题名称策略。
本安装推荐手动安装(未使用confluent-hub)。
/share/kafka/plugins
(自定义此路径)然后复制连接器插件的内容。plugin.path=/usr/local/share/kafka/plugins
(自定义的路径)Kafka Connect使用其插件路径查找插件。插件路径是在Kafka Connect的worker配置中定义的目录的逗号分隔列表。curl -X GET http://localhost:8083/connector-plugins
此快速入门使用HDFS连接器将Avro控制台生产者产生的数据导出到HDFS。请确保Hadoop在本地或远程运行,并且您知道HDFS URL。对于Hive集成,您需要安装Hive并了解metastore thrift URI。此快速入门假定您使用默认配置启动了所需的服务,并且应根据使用的实际配置进行必要的更改。
注意: 您需要确保连接器用户对
topics.dir
和中指定的目录具有写权限logs.dir
。的默认值topics.dir
是/topics
和的默认值logs.dir
是/logs
。如果您未指定两个配置,请确保连接器用户对/topics
和具有写权限/logs
。您可能需要先创建/topics
和/logs
在运行连接器之前,因为连接器可能没有对的写权限/
。
# 流作业
curl -i -k -H "Content-type: application/json" -X POST -d '{
"name": "hdfs3-sink-hive",
"config": {
"connector.class": "io.confluent.connect.hdfs.HdfsSinkConnector",
"tasks.max": "1",
"topics": "dataxhive",
"hdfs.url": "hdfs://master:9002",
"flush.size": "3",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://master:8081",
"confluent.topic.bootstrap.servers": "slaver:9092",
"confluent.topic.replication.factor": "1",
"hive.integration":"true",
"hive.metastore.uris":"thrift://master:9083",
"schema.compatibility":"BACKWARD"
}
}' http://localhost:8083/connectors
注意:前几个设置是您将为所有连接器指定的通用设置。该
topics
参数指定要从中导出数据的主题。在这种情况下dataxtest
。hdfs.url
指定已写入数据的HDFS。您应该根据您的配置进行设置。flush.size
指定在调用文件提交之前连接器需要写入的记录数(重要此参数控制着什么时间刷新并提交文件,可能会造成数据丢失)。对于高可用性HDFS部署,设置hadoop.conf.dir
为包含的目录hdfs-site.xml
。之后hdfs-site.xml
到位,并hadoop.conf.dir
已定,hdfs.url
可设置为namenodes名称服务ID,例如nameservice1
。
# 批作业读取数据后写入hdfs中并创建hive外部表
curl -i -k -H "Content-type: application/json" -X POST -d '{
"name": "hdfs3-sink-hive",
"config": {
"connector.class": "io.confluent.connect.hdfs.HdfsSinkConnector",
"tasks.max": "1",
"topics": "dataxhive",
"hdfs.url": "hdfs://master:9002",
"flush.size": "3",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://slaver:8081",
"confluent.topic.bootstrap.servers": "master:9092",
"confluent.topic.replication.factor": "1",
"hive.integration":"true",
"hive.metastore.uris":"thrift://master:9083",
"schema.compatibility":"BACKWARD",
"type":"key",
"offsetKey":"dataxhive"
}
}' http://localhost:8083/connectors
# 查询现有的作业
curl -X GET http://localhost:8083/connectors
# 删除指定的作业
curl -X DELETE http://localhost:8083/connectors/hdfs3-sink
要使用此连接器,请在connector.class
配置属性中指定连接器类的名称。
connector.class=io.confluent.connect.hdfs.HdfsSinkConnector
连接器特定的配置属性如下所述。
hdfs.url
HDFS连接URL。此配置的格式为hdfs :: // hostname:port,并指定要将数据导出到的HDFS。此属性已弃用,并将在以后的版本中删除。使用store.url
代替。
hadoop.conf.dir
Hadoop配置目录。
hadoop.home
Hadoop主目录。
logs.dir
顶级目录,用于存储预写日志。
hdfs.authentication.kerberos
指示HDFS是否使用Kerberos进行身份验证的配置。
connect.hdfs.principal
,connect.hdfs.keytab
,hdfs.namenode.principal
,kerberos.ticket.renew.period.ms
connect.hdfs.principal
HDFS使用Kerberos进行身份验证时使用的主体。
connect.hdfs.keytab
HDFS连接器主体的密钥表文件的路径。此密钥表文件仅应由连接器用户读取。
hdfs.namenode.principal
HDFS Namenode的主体。
kerberos.ticket.renew.period.ms
续订Kerberos票证的时间(以毫秒为单位)。
format.class
将数据写入存储时使用的格式类。格式类实现io.confluent.connect.storage.format.Format
接口。
io.confluent.connect.hdfs.avro.AvroFormat
这些类默认情况下可用:
io.confluent.connect.hdfs.avro.AvroFormat
io.confluent.connect.hdfs.json.JsonFormat
io.confluent.connect.hdfs.parquet.ParquetFormat
io.confluent.connect.hdfs.string.StringFormat
flush.size
在调用文件提交之前写入存储的记录数。
rotate.interval.ms
调用文件提交的时间间隔(以毫秒为单位)。此配置可确保在每个配置的间隔内调用文件提交。当数据摄取率较低且连接器未写入足够的消息来提交文件时,此配置很有用。默认值-1表示此功能已禁用。
rotate.schedule.interval.ms
定期调用文件提交的时间间隔(以毫秒为单位)。此配置可确保在每个配置的间隔内调用文件提交。提交时间将调整为所选时区的00:00。无论先前的提交时间或消息数量如何,提交都将在计划的时间执行。当您必须基于当前服务器时间(例如每小时开始时)提交数据时,此配置很有用。默认值-1表示此功能已禁用。
schema.cache.size
Avro转换器中使用的架构缓存的大小。
retry.backoff.ms
重试退避(以毫秒为单位)。此配置用于通知Connect,以在发生临时异常时重试传递消息批处理或执行恢复。
shutdown.timeout.ms
清除关机超时。这样可以确保在连接器关闭期间完成异步Hive Metastore更新。
filename.offset.zero.pad.width
如果偏移量太短,则商店的文件名中的宽度到零填充的偏移量可以提供固定宽度的文件名,可以通过简单的词典编目排序对其进行排序。
storage.class
基础存储层。
topics.dir
顶级目录,用于存储从ApacheKafka®提取的数据。
store.url
商店的连接URL(如果适用)。例如:hdfs://hostname:port
。
directory.delim
目录定界符模式
file.delim
文件分隔符模式
partitioner.class
将数据写入存储时使用的分区程序。以下分区可用:
DefaultPartitioner
保留Kafka分区。
DailyPartitioner
根据日期对数据进行分区。
HourlyPartitioner
根据小时划分数据。
FieldPartitioner
根据中指定的分区字段的值将数据分区到不同的目录partition.field.name
。
TimeBasedPartitioner
根据摄取时间对数据进行分区。
类型:类
默认值:io.confluent.connect.storage.partitioner.DefaultPartitioner
重要性:高
家属:partition.field.name
,partition.duration.ms
,path.format
,locale
,timezone
partition.field.name
使用分区字段的名称FieldPartitioner
。您可以使用逗号分隔的名称输入多个分区字段名称。
partition.duration.ms
所使用的分区毫秒数的持续时间TimeBasedPartitioner
。默认值-1表示我们不使用TimeBasedPartitioner
。
path.format
当使用进行分区时,此配置用于设置数据目录的格式TimeBasedPartitioner
。在此配置中设置的格式将Unix时间戳转换为正确的目录字符串。例如,如果设置path.format='year'=YYYY/'month'=MM/'day'=dd/'hour'=HH
,则数据目录的格式为/year=2015/month=12/day=07/hour=15/
。
locale
使用进行分区时使用的语言环境TimeBasedPartitioner
,用于格式化日期和时间。例如,en-US
用于美国英语,en-GB
英国英语或fr-FR
法语(在法国)。这些可能因Java版本而异。查看可用的语言环境。
timezone
使用进行分区时要使用的时区TimeBasedPartitioner
,用于格式化和计算日期和时间。使用时区的标准短名称如UTC
或(无日光节约)PST
,EST
和ECT
,或更长的标准名称,如America/Los_Angeles
,America/New_York
,和Europe/Paris
。这些可能因Java版本而异。查看每个语言环境中的可用时区,例如美国英语语言环境中的可用时区。
timestamp.extractor
使用进行分区时获取记录时间戳记的提取器TimeBasedPartitioner
。可以将其设置为Wallclock
,Record
或者RecordField
使用内置的时间戳提取器之一,或者为其指定扩展TimestampExtractor
接口的用户定义类的标准类名。
timestamp.field
时间戳提取器用作时间戳的记录字段。
hive.integration
指示运行连接器时是否与Hive集成的配置。
hive.metastore.uris
,hive.conf.dir
,hive.home
,hive.database
,schema.compatibility
hive.metastore.uris
Hive Metastore URI可以是IP地址或Metastore主机的标准域名和端口。
hive.conf.dir
配置单元配置目录
hive.home
配置单元主目录。
hive.database
连接器在Hive中创建表时要使用的数据库。
schema.compatibility
连接器观察架构更改时要使用的架构兼容性规则。支持的配置为NONE,BACKWARD,FORWARD和FULL。
如果要将其他格式写入HDFS或使用其他分区程序format.class
,partitioner.class
则需要指定和。以下示例配置演示了如何编写Parquet格式和使用每小时分区程序:
format.class=io.confluent.connect.hdfs.parquet.ParquetFormat
partitioner.class=io.confluent.connect.hdfs.partitioner.HourlyPartitioner
注意:
如果要使用字段分区器,则还需要指定
partition.field.name
配置以指定记录的字段名称。
至少,你需要指定hive.integration
,hive.metastore.uris
并 schema.compatibility
整合蜂巢时。这是一个示例配置:
hive.integration=true
hive.metastore.uris=thrift://localhost:9083 # FQDN for the host part
schema.compatibility=BACKWARD
您应该hive.metastore.uris
根据您的Hive配置进行调整。
注意
如果您未指定hive.metastore.uris
,则连接器将在运行连接器的目录中将本地元存储与Derby一起使用。您需要在此目录中运行Hive才能查看Hive元数据的更改。
注意
由于连接器任务长时间运行,因此与Hive Metastore的连接将保持打开状态,直到任务停止为止。在默认的Hive配置中,重新连接到Hive Metastore将创建一个新连接。当任务数量很大时,重试可能导致打开的连接数超过操作系统中允许的最大连接数。因此建议设置hcatalog.hive.client.cache.disabled
为true
in hive.xml
。
此外,为了支持模式演变的schema.compatibility
是BACKWARD
,FORWARD
和 FULL
。这样可以确保Hive可以使用最新的Hive表架构查询使用不同架构写入HDFS的数据。有关架构兼容性的更多信息,请参见Schema Evolution。
要使用安全的HDFS和蜂巢metastore工作,你需要指定hdfs.authentication.kerberos
, connect.hdfs.principal
,connect.keytab
,hdfs.namenode.principal
:
hdfs.authentication.kerberos=true
connect.hdfs.principal=connect-hdfs/[email protected]
connect.hdfs.keytab=path to the connector keytab
hdfs.namenode.principal=namenode principal
您需要通过Kerberos创建Kafka连接主体和密钥表文件,并将密钥表文件分发给运行连接器的所有主机,并确保只有连接器用户具有对密钥表文件的读取访问权限。
注意
当启用安全,您需要使用的FQDN的主机部分 hdfs.url
和hive.metastore.uris
。
注意
当前,连接器要求在运行连接器的所有主机上,主体和密钥表路径必须相同。hdfs.namenode.prinicipal
需求的主机部分必须是Namenode主机的实际FQDN,而不是_HOST
占位符。
重要
仅当使用默认命名策略()生成记录时,方案演化才有效TopicNameStrategy
。如果使用其他命名策略,则可能会发生错误。这是因为记录彼此不兼容。如果使用其他命名策略,schema.compatibility
则应设置为NONE
。这可能会导致目标文件较小,因为每次模式ID在记录之间更改时,接收器连接器都会创建一个新文件。有关命名策略的更多信息,请参见主题名称策略。
HDFS连接器支持架构演变,并根据schema.compatibility
配置对数据的架构更改做出反应 。在本部分中,我们将说明连接器如何在不同的值下对架构演变做出反应schema.compatibility
。的 schema.compatibility
可设置为NONE
,BACKWARD
,FORWARD
和FULL
,这意味着没有兼容性,向后兼容性,前向兼容性和FULL兼容性分别。
否兼容性:默认情况下,schema.compatibility
设置为NONE
。在这种情况下,连接器确保每个写入HDFS的文件都具有正确的架构。当连接器观察到数据中的架构更改时,它会为受影响的主题分区提交当前文件集,并将具有新架构的数据写入新文件中。
向后兼容性:如果以向后兼容的方式发展模式,我们总是可以使用最新的模式统一查询所有数据。例如,删除字段是对模式的向后兼容更改,因为当我们遇到使用旧模式编写的包含这些字段的记录时,我们可以忽略它们。添加具有默认值的字段也向后兼容。
如果BACKWARD
在中指定schema.compatibility
,则连接器将跟踪用于将数据写入HDFS的最新模式,并且如果到达具有比当前最新模式更大的模式版本的数据记录,则连接器将提交当前文件集并写入数据记录与新架构的新文件。对于使用较早版本的架构在以后到达的数据记录,连接器将数据记录投影到最新的架构,然后再写入HDFS中的同一组文件。
FORWARD兼容性:如果以向前兼容的方式发展模式,我们总是可以使用最早的模式统一查询所有数据。删除具有默认值的字段是向前兼容的,因为缺少该字段时,旧模式将使用默认值。
如果FORWARD
在中指定schema.compatibility
,则连接器会将数据投影到最早的架构,然后再写入HDFS中的同一组文件。
完全兼容性:完全兼容性意味着可以使用新架构读取旧数据,也可以使用旧架构读取新数据。
如果FULL
在中指定schema.compatibility
,则连接器执行与相同的操作BACKWARD
。
如果蜂巢集成启用时,我们需要指定schema.compatibility
为BACKWARD
, FORWARD
或FULL
。这样可以确保Hive表架构能够查询使用不同架构编写的主题下的所有数据。如果将schema.compatibility
设置为BACKWARD
或 FULL
,则主题的Hive表架构将等同于该主题下的HDFS文件中的最新架构,该架构可以查询该主题的整个数据。如果将schema.compatibility
设置为FORWARD
,则主题的Hive表架构等同于该主题下的HFDS文件的最早架构,该架构可以查询该主题的整个数据。
通过Kafka Connect JDBC源连接器,您可以使用JDBC驱动程序将任何关系数据库中的数据导入ApacheKafka®主题。通过使用JDBC,此连接器可以支持各种数据库,而无需为每个数据库使用自定义代码。
通过定期执行SQL查询并为结果集中的每一行创建输出记录来加载数据。默认情况下,数据库中的所有表都被复制,每个表都复制到其自己的输出主题。监视数据库中的新表或删除表,并自动进行调整。从表复制数据时,连接器可以通过指定应使用哪些列来检测新数据或修改的数据来仅加载新行或修改的行。
您可以配置Java流应用程序以多种方式反序列化和摄取数据,包括Kafka控制台生产者,JDBC源连接器和Java客户端生产者。有关完整的代码示例,请参见connect-streams-pipeline。
每种增量查询模式都为每一行跟踪一组列,用于跟踪已处理的行以及哪些行是新的或已更新的行。该mode
设置控制此行为,并支持以下选项:
AUTOINCREMENT
列。请注意,此模式只能检测新行。无法检测到对现有行的更新,因此该模式仅应用于不可变数据。在数据仓库中流化事实表时,您可能会使用此模式的一个示例,因为这些表通常是仅插入的。递增列必须是整数类型。WHERE
子句正确附加到查询中,就可以使用其他更新自动更新模式之一。或者,指定的查询可以自己处理对新更新的过滤。但是,请注意,将不会执行偏移量跟踪(与为每个记录记录incrementing
和/或timestamp
列值的自动模式不同 ),因此查询必须跟踪偏移量本身。请注意,使用某些列来检测更改的所有增量查询模式都将需要这些列上的索引才能有效地执行查询。
对于使用时间戳的增量查询模式,源连接器将使用一种配置 timestamp.delay.interval.ms
来控制在将包含特定时间戳的行出现在结果中之前的等待时间。额外的等待时间可以使带有较早时间戳记的事务完成,并将相关的更改包括在结果中。有关更多信息,请参见配置属性。
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"
}
}'
源连接器具有一些选项,用于控制如何将列类型映射到“连接”字段类型。默认情况下,连接器将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
。
源连接器使您可以灵活地从中导入数据的数据库以及如何导入数据的灵活性。本节首先介绍如何访问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
使用Avro转换器时,JDBC连接器支持架构演变。当数据库表架构发生更改时,JDBC连接器可以检测到更改,创建新的Connect架构,并尝试在Schema Registry中注册新的Avro架构。是否可以成功注册架构取决于架构注册表的兼容性级别,默认情况下该兼容性级别是向后的。
例如,如果您从表中删除一列,则更改是向后兼容的,并且相应的Avro架构可以在Schema Registry中成功注册。如果您修改数据库表架构以更改列类型或添加列,则将Avro架构注册到架构注册表时,由于更改不向后兼容,它将被拒绝。
您可以更改架构注册表的兼容性级别,以允许不兼容的架构或其他兼容性级别。有两种方法可以做到这一点:
PUT /config/(string: subject)``topic-key``topic-value``topic``topic.prefix
avro.compatibility.level
在架构注册表中进行设置,将架构注册表配置为使用其他架构兼容性级别 。请注意,这是一个全局设置,适用于架构注册表中的所有架构。但是,由于JDBC API的限制,某些兼容的架构更改可能被视为不兼容的更改。例如,添加具有默认值的列是向后兼容的更改。但是,由于JDBC API的局限性,很难将其映射到Kafka Connect模式中正确类型的默认值,因此当前省略了默认值。其含义是,即使数据库表架构的某些更改是向后兼容的,在Schema Registry中注册的架构也不是向后兼容的,因为它不包含默认值。
如果将JDBC连接器与HDFS连接器一起使用,则对模式兼容性也有一些限制。启用Hive集成后,需要向后,向前和完整的架构兼容性,以确保Hive架构能够查询某个主题下的全部数据。由于某些兼容的架构更改将被视为不兼容的架构更改,因此这些更改将不起作用,因为生成的Hive架构将无法查询整个数据中的某个主题。
要使用此连接器,请在connector.class
配置属性中指定连接器类的名称。
connector.class=io.confluent.connect.jdbc.JdbcSourceConnector
连接器特定的配置属性如下所述。
在连接器配置中,您会注意到没有安全参数。这是因为SSL不属于JDBC标准,而是取决于所使用的JDBC驱动程序。通常,您需要通过connection.url
参数配置SSL 。例如,对于MySQL,它看起来像:
connection.url="jdbc:mysql://127.0.0.1:3306/sample?verifyServerCertificate=false&useSSL=true&requireSSL=true"
请查阅有关支持和配置的特定JDBC驱动程序文档。
connection.url
JDBC连接URL。
table.whitelist
,table.blacklist
connection.user
JDBC连接用户。
connection.password
JDBC连接密码。
connection.attempts
检索有效JDBC连接的最大尝试次数。
connection.backoff.ms
两次连接尝试之间的退避时间(以毫秒为单位)。
catalog.pattern
目录模式以从数据库中获取表元数据。
table.whitelist
要包括在复制中的表的列表。如果指定,则table.blacklist
可能未设置。使用逗号分隔的列表来指定多个表(例如)。table.whitelist: "User, Address, Email"
table.blacklist
列表中要排除的表。如果指定,则table.whitelist
可能未设置。使用逗号分隔的列表来指定多个表(例如)。table.blacklist: "User, Address, Email"
schema.pattern
从数据库中获取表元数据的模式模式。
类型:字符串
默认值:空
""
检索那些没有模式的。重要性:高
重要
如果将其保留为默认的null设置,则连接器可能会超时并失败,原因是接收到大量的表元数据。确保为大型数据库设置此参数。
numeric.precision.mapping
是否尝试通过精度将NUMERIC值映射到整数类型。现在不推荐使用此选项。将来的版本可能会完全删除它。请numeric.mapping
改用。
numeric.mapping
通过精度映射NUMERIC值,还可以选择缩放为整数或十进制类型。
none
如果所有的数字列被连接的DECIMAL逻辑类型来表示。best_fit
如果数值列应基于列的精度和规模转换为连接的INT8,INT16,INT32,INT64或FLOAT64。precision_only
映射仅基于列的精度假设列的比例为0数字列。none
选项是默认选项,但由于Connect的DECIMAL类型映射到其二进制表示形式,因此可能会导致Avro的序列化问题,并且best_fit
由于它映射到最合适的原始类型而经常会被首选。dialect.name
该连接器应使用的数据库方言的名称。默认情况下为空,并且连接器根据JDBC连接URL自动确定方言。如果要覆盖该行为并使用特定的方言,请使用此选项。可以使用JDBC连接器插件中所有正确包装的方言。
, Db2DatabaseDialect, MySqlDatabaseDialect, SybaseDatabaseDialect, GenericDatabaseDialect, OracleDatabaseDialect
,SqlServerDatabaseDialect, PostgreSqlDatabaseDialect, SqliteDatabaseDialect, DerbyDatabaseDialect
, SapHanaDatabaseDialect, MockDatabaseDialect, VerticaDatabaseDialect
mode
每次轮询表时更新表的方式。选项包括:
incrementing.column.name
,timestamp.column.name
,validate.non.null
incrementing.column.name
严格递增的列的名称,用于检测新行。任何空值表示应通过查找自动递增的列来自动检测该列。该列可能不能为空。
timestamp.column.name
用一个或多个时间戳列的逗号分隔列表,以使用COALESCE SQL函数检测新行或修改过的行。每次轮询都会发现第一个非空时间戳值大于看到的最大先前时间戳值的行。至少一列不应为空。
validate.non.null
默认情况下,JDBC连接器将验证所有增量表和时间戳表是否将NOT NULL设置为用作其ID /时间戳的列。如果没有这些表,则JDBC连接器将无法启动。将此设置为false将禁用这些检查。
query
如果指定,则执行查询以选择新的或更新的行。如果要联接表,选择表中列的子集或过滤数据,请使用此设置。如果使用此连接器,则将仅使用此查询复制数据–整个表复制将被禁用。仍然可以使用不同的查询模式进行增量更新,但是为了正确地构造增量查询,必须有可能在此查询后附加WHERE子句(即,不得使用WHERE子句)。如果使用WHERE子句,则它本身必须处理增量查询。
quote.sql.identifiers
何时在SQL语句中引用表名,列名和其他标识符。为了向后兼容,默认值为always
。
table.types
默认情况下,JDBC连接器将仅从源数据库中检测类型为TABLE的表。此配置允许提取命令分隔的表类型列表。
类型: list.
TABLE
VIEW
SYSTEM TABLE
GLOBAL TEMPORARY
LOCAL TEMPORARY
ALIAS
SYNONYM
在大多数情况下,只有TABLE或VIEW才有意义。
默认值:TABLE
重要性:低
poll.interval.ms
以毫秒为单位的频率,用于轮询每个表中的新数据。
batch.max.rows
轮询新数据时,单个批处理中包含的最大行数。此设置可用于限制连接器内部缓冲的数据量。
table.poll.interval.ms
轮询新表或删除表的频率(以毫秒为单位),这可能导致更新的任务配置开始对添加表中的数据进行轮询或停止对删除表中的数据进行轮询。
topic.prefix
在表名之前添加前缀,以生成要向其发布数据的ApacheKafka®主题的名称,或者在自定义查询的情况下,生成要发布到的主题的全名。
timestamp.delay.interval.ms
在将其包含在结果中之前,出现具有特定时间戳记的行之后需要等待多长时间。您可以选择添加一些延迟,以允许时间戳较早的事务完成。第一次执行将获取所有可用记录(即从时间戳0开始),直到当前时间减去延迟为止。接下来的每一次执行都会从上一次获取数据到当前时间减去延迟。
db.timezone
使用基于时间的条件进行查询时,连接器中使用的JDBC时区的名称。默认为UTC。
-----------------------------示例JDBC Source---------------------------------------
curl -i -k -H "Content-type: application/json" -X POST -d '{
"name": "jdbc-source",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"tasks.max": "1",
"connection.url":"jdbc:mysql://mysql:3306/test",
"mode": "incrementing",
"connection.user":"root",
"connection.password":"root",
"dialect.name":"MySqlDatabaseDialect",
"table.whitelist":"test",
"schema.pattern":"",
"numeric.mapping":"best_fit",
"incrementing.column.name": "id",
"topic.prefix": "jdbc-source",
"key.converter":"org.apache.kafka.connect.storage.StringConverter",
"value.converter":"io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://master:8081"
}
}' http://localhost:8083/connectors
Kafka Connect JDBC接收器连接器允许您使用JDBC驱动程序将数据从ApacheKafka®主题导出到任何关系数据库。通过使用JDBC,此连接器可以支持各种数据库,而无需为每个数据库使用专用的连接器。连接器根据主题订阅从Kafka轮询数据以写入数据库。可以通过upserts实现幂等写入。还支持表的自动创建和有限的自动演化。
接收器连接器需要架构知识,因此您应该使用合适的转换器,例如,架构注册表附带的Avro转换器或启用了架构的JSON转换器。Kafka记录键(如果存在)可以是原始类型或Connect结构,并且记录值必须是Connect结构。从“连接”结构中选择的字段必须是原始类型。如果主题中的数据不是兼容格式,则Converter
可能需要实现自定义。
缺省情况是,在pk.mode
设置为none的情况下,不提取主键,这不适合高级用法(例如upsert语义)以及连接器负责自动创建目标表的情况。有多种模式可以使用来自Kafka记录键,Kafka记录值或该记录的Kafka坐标的字段。
有关更多详细信息,请参阅主键配置选项。
连接器使用逻辑删除记录时,该连接器可以删除数据库表中的行,该记录是具有非null键和null值的Kafka记录。默认情况下,此行为是禁用的,这意味着任何逻辑删除记录都将导致连接器发生故障,从而可以轻松升级JDBC连接器并保持先前的行为。
可以使用启用删除delete.enabled=true
,但只有将pk.mode
设置为时才可以启用record_key
。这是因为从表中删除一行需要将主键用作条件。
启用删除模式不会影响insert.mode
。
默认insert.mode
值为insert
。如果将其配置为upsert
,则连接器将使用upsert语义而不是简单的INSERT
语句。Upsert语义是指在存在主键约束冲突的情况下原子地添加新行或更新现有行,从而提供了幂等性。
如果存在故障,则用于恢复的Kafka偏移量可能与故障发生时未提交的内容保持最新,这可能导致恢复期间进行重新处理。强烈建议使用upsert模式,因为如果需要重新处理记录,它将有助于避免违反约束或重复数据。
除了故障恢复外,源主题还可以自然地随时间包含具有相同主键的多个记录,因此需要高证书。
由于没有用于upsert的标准语法,因此下表描述了所使用的特定于数据库的DML。
Database | Upsert style |
---|---|
MySQL | INSERT .. ON DUPLICATE KEY REPLACE .. |
Oracle | MERGE .. |
PostgreSQL | INSERT .. ON CONFLICT .. DO UPDATE SET .. |
SQLite | INSERT OR REPLACE .. |
SQL Server | MERGE .. |
Other | not supported |
如果auto.create
启用,则连接器可以在发现目标表丢失的情况下创建目标表。由于连接器使用记录架构作为表定义的基础,因此创建是在线进行的,并使用了从该主题消费的记录。主键是根据键配置设置指定的。
如果auto.evolve
启用此功能,则当连接器遇到发现缺少某列的记录时,可以通过在目标表上发出ALTER来执行有限的自动演化。由于数据类型的更改和列的删除可能很危险,因此连接器不会尝试在表上执行此类更改。也没有尝试添加主键约束。相反,如果auto.evolve
禁用此选项,则不会执行任何演化,并且连接器任务将失败,并显示一条错误,指出缺少的列。
对于自动创建和自动演化,列的可空性基于架构中相应字段的可选性,并且如果适用,还基于相应字段的默认值指定默认值。我们使用以下从Connect模式类型到特定于数据库类型的映射:
要使用此连接器,请在connector.class
配置属性中指定连接器类的名称。
connector.class=io.confluent.connect.jdbc.JdbcSinkConnector
连接器特定的配置属性如下所述。
在连接器配置中,您会注意到没有安全参数。这是因为SSL不属于JDBC标准,而是取决于所使用的JDBC驱动程序。通常,您需要通过connection.url
参数配置SSL 。例如,对于MySQL,它看起来像:
connection.url="jdbc:mysql://127.0.0.1:3306/sample?verifyServerCertificate=false&useSSL=true&requireSSL=true"
请查阅有关支持和配置的特定JDBC驱动程序文档。
connection.url
JDBC连接URL。
connection.user
JDBC连接用户。
connection.password
JDBC连接密码。
dialect.name
该连接器应使用的数据库方言的名称。默认情况下为空,并且连接器根据JDBC连接URL自动确定方言。如果要覆盖该行为并使用特定的方言,请使用此选项。可以使用JDBC连接器插件中所有正确包装的方言。
insert.mode
要使用的插入模式。支持的模式有:
insert
使用标准的SQL INSERT
语句。
upsert
如果连接器支持目标数据库,请使用适当的upsert语义,例如。INSERT OR IGNORE
update
如果连接器支持目标数据库,请使用适当的更新语义,例如UPDATE
。
类型:字符串
默认值:插入
有效值:[插入,向上插入,更新]
重要性:高
batch.size
指定在可能的情况下尝试将多少记录一起批处理以插入到目标表中。
delete.enabled
是否将null
记录值视为删除。要求pk.mode
是record_key
。
table.name.format
目标表名称的格式字符串,其中可以包含“ $ {topic}”作为源主题名称的占位符。
例如,kafka_${topic}
对于主题“订单”将映射到表名称“ kafka_orders”。
pk.mode
主键模式,也请参考pk.fields
文档以了解交互作用。支持的模式有:
none
没有使用键。
kafka
ApacheKafka®坐标用作PK。
record_key
使用了来自记录键的字段,该字段可以是基元或结构。
record_value
使用记录值中的字段,该字段必须是结构。
类型:字符串
默认值:无
有效值:[none,kafka,record_key,record_value]
重要性:高
pk.fields
逗号分隔的主键字段名称列表。此配置的运行时解释取决于pk.mode
:
none
在此模式下,由于没有字段用作主键,因此将被忽略。
kafka
必须是代表Kafka坐标的三重奏,__connect_topic,__connect_partition,__connect_offset
如果为空则默认为。
record_key
如果为空,则将使用键结构中的所有字段,否则将用于提取所需的字段-对于原始键,仅必须配置一个字段名称。
record_value
如果为空,将使用值struct中的所有字段,否则将提取所需的字段。
类型:清单
默认值:无
重要性:中等
fields.whitelist
以逗号分隔的记录值字段名称的列表。如果为空,将使用记录值中的所有字段,否则将用于过滤到所需的字段。
请注意,pk.fields
在哪个字段在目标数据库中构成主键列的上下文中独立应用,而此配置适用于其他列。
db.timezone
插入基于时间的值时,连接器应使用的JDBC时区的名称。默认为UTC。
auto.create
如果通过发出发现缺少记录表,是否基于记录模式自动创建目标表CREATE
。
auto.evolve
通过发出相对于记录架构丢失时是否在表架构中自动添加列ALTER
。
quote.sql.identifiers
何时在SQL语句中引用表名,列名和其他标识符。为了向后兼容,默认值为always
。
max.retries
任务失败前重试错误的最大次数。类型:int默认值:10有效值:[0,…]重要性:中等
retry.backoff.ms
错误尝试重试之前等待的时间(以毫秒为单位)。类型:int默认值:3000有效值:[0,…]重要性:中等
------------------------------------流处理---------------------------------------
curl -i -k -H "Content-type: application/json" -X POST -d '{
"name":"mysql-sink",
"config":{
"connector.class":"io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url":"jdbc:mysql://mysql:3306/test",
"connection.user":"root",
"connection.password":"root",
"dialect.name":"MySqlDatabaseDialect",
"topics":"dataxhive",
"insert.mode":"upsert",
"table.name.format":"test1",
"pk.mode":"record_value",
"pk.fields":"id",
"tasks.max":"1",
"key.converter":"org.apache.kafka.connect.storage.StringConverter",
"value.converter":"io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://master:8081"
}
}' http://localhost:8083/connectors
------------------------------------mudesa--------------------------------------
curl -i -k -H "Content-type: application/json" -X POST -d '{
"name":"mysql-sink",
"config":{
"connector.class":"io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url":"jdbc:mysql://mysql:3306/test",
"connection.user":"root",
"connection.password":"root",
"dialect.name":"MySqlDatabaseDialect",
"topics":"dataxhive",
"insert.mode":"upsert",
"table.name.format":"test1",
"pk.mode":"record_value",
"pk.fields":"id",
"tasks.max":"1",
"key.converter":"org.apache.kafka.connect.storage.StringConverter",
"value.converter":"io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://master:8081",
"type":"key",
"offsetKey":"dataxhive"
}
}' http://localhost:8083/connectors
1 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
2 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
3 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
4 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
5 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
6 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
7 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
8 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
9 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
10 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
11 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
12 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
13 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
14 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
15 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
16 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
17 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
18 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
19 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
20 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
21 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
22 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
23 1.20 1.055 1.25 2020-05-16 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
1 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
2 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
3 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
4 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
5 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
6 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
7 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
8 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
9 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
10 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
11 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
12 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
13 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
14 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
15 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
16 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
17 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
18 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
19 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
20 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
21 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
22 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
23 1.20 1.055 1.25 2020-05-15 dadadas 16:04:42.000000 2020-05-16 16:04:47.000000
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/data/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/data/hive/lib/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
2020-05-17 15:15:01,030 INFO [main] conf.HiveConf (HiveConf.java:findConfigFile(187)) - Found configuration file file:/data/hive/conf/hive-site.xml
Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
at org.apache.hadoop.conf.Configuration.set(Configuration.java:1357)
at org.apache.hadoop.conf.Configuration.set(Configuration.java:1338)
at org.apache.hadoop.mapred.JobConf.setJar(JobConf.java:518)
at org.apache.hadoop.mapred.JobConf.setJarByClass(JobConf.java:536)
at org.apache.hadoop.mapred.JobConf.<init>(JobConf.java:430)
at org.apache.hadoop.hive.conf.HiveConf.initialize(HiveConf.java:5141)
at org.apache.hadoop.hive.conf.HiveConf.<init>(HiveConf.java:5099)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4jCommon(LogUtils.java:97)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4j(LogUtils.java:81)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:699)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:683)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.util.RunJar.run(RunJar.java:318)
at org.apache.hadoop.util.RunJar.main(RunJar.java:232)
------------------------------------解决方案------------------------------------------
com.google.common.base.Preconditions.checkArgument 这是因为hive内依赖的guava.jar和hadoop内的版本不一致造成的。
hiveserver2启动不了端口10000解决过程
Decimal精确度引起的Hive不能解析问题
解决思路参考
------------------------------HDFS插件自动建表的sql语句-----------------
CREATE EXTERNAL TABLE `dataxhive1`(
)
PARTITIONED BY (
`partition` string COMMENT '')
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
LOCATION
'hdfs://master:9002/topics/dataxhive'
TBLPROPERTIES (
'avro.schema.literal'='{"type":"record","name":"dataxhive","fields":[{"name":"id","type":["null",{"type":"int","connect.name":"INT"}],"default":null},{"name":"a","type":["null",{"type":"double","connect.name":"DOUBLE"}],"default":null},{"name":"b","type":["null",{"type":"float","connect.name":"FLOAT"}],"default":null},{"name":"c","type":["null",{"type":"bytes","scale":2,"precision":64,"connect.version":1,"connect.parameters":{"scale":"2"},"connect.name":"org.apache.kafka.connect.data.Decimal","logicalType":"decimal"}],"default":null},{"name":"d","type":["null",{"type":"int","connect.version":1,"connect.name":"org.apache.kafka.connect.data.Date","logicalType":"date"}],"default":null},{"name":"e","type":["null",{"type":"string","connect.name":"STRING"}],"default":null},{"name":"f","type":["null",{"type":"int","connect.version":1,"connect.name":"org.apache.kafka.connect.data.Time","logicalType":"time-millis"}],"default":null},{"name":"g","type":["null",{"type":"long","connect.version":1,"connect.name":"org.apache.kafka.connect.data.Timestamp","logicalType":"timestamp-millis"}],"default":null}],"connect.version":1,"connect.name":"dataxhive"}',
'transient_lastDdlTime'='1589767539')
# 获取所有任务
curl -X GET http://localhost:8083/connectors
# 删除指定任务
curl -X DELETE http://localhost:8083/connectors/hdfs3-sink
# metastore 后台运行
nohup hive --service metastore 1>/dev/null 2>&1 &
# hiveserver2 后台运行
nohup hiveserver2 1>/dev/null 2>&1 &
# 进入hiveSql
beeline -u jdbc:hive2://localhost:10000 -n root
# 获取Kafka集群消费组
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
# 删除指定的消费组
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --delete --group test
/*
Navicat MySQL Data Transfer
Source Server : master
Source Server Version : 50721
Source Host : master:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50721
File Encoding : 65001
Date: 2020-05-18 17:01:06
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for test
-- ----------------------------
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` double(255,2) DEFAULT NULL,
`b` float(255,3) DEFAULT NULL,
`c` decimal(56,2) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` varchar(255) DEFAULT NULL,
`f` time(6) DEFAULT NULL,
`g` datetime(6) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO `test` VALUES ('1', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('2', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('3', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('4', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('5', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('6', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('7', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('8', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('9', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('10', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('11', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('12', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('13', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('14', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('15', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('16', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('17', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('18', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('19', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('20', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('21', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('22', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
INSERT INTO `test` VALUES ('23', '1.20', '1.055', '1.25', '2020-05-16', 'dadadas', '16:04:42.000000', '2020-05-16 16:04:47.000000');
{
"job":{
"setting":{
"speed":{
"channel":1
},
"errorLimit":{
"record":0,
"percentage":0.02
}
},
"content":[
{
"reader":{
"name":"mysqlreader",
"parameter":{
"username":"root",
"password":"",
"column":[
"id",
"a",
"b",
"c",
"d",
"e",
"f",
"g"
],
"connection":[
{
"table":[
"test"
],
"jdbcUrl":[
"jdbc:mysql://master:3306/test"
]
}
]
}
},
"writer":{
"name":"kafkaWriter",
"parameter":{
"kafkaConfig":{
"bootstrap.servers":"master:9092,slaver:9092"
},
"topics":"dataxhive",
"column":{
"type":"record",
"name":"dataxhive",
"fields":[
{
"name":"id",
"type":"int",
"index":0
},
{
"name":"a",
"type":"double",
"index":1
},
{
"name":"b",
"type":"float",
"index":2
},
{
"name":"c",
"type":"decimal",
"scale":2,
"index":3
},
{
"name":"d",
"type":"date",
"index":4
},
{
"name":"e",
"type":"string",
"index":5
},
{
"name":"f",
"type":"time",
"index":6
},
{
"name":"g",
"type":"datetime",
"index":7
}
]
},
"medusa":{
"hostName":"http://192.168.101.42:8083,http://192.168.101.43:8083",
"name":"dataxhive"
},
"schemaRegistry":{
"schema.registry.url":"http://192.168.101.43:8081",
"schemas.enable":true,
"value.converter":"io.confluent.connect.avro.AvroConverter"
}
}
}
}
]
}
}