flink - sink - hive

依赖

以下依赖均可以放到flink lib中,然后在pom中声明为provided

flink对hive的核心依赖

复制代码
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-connector-hive_${scala.version}</artifactId>
    <version>${flink.version}</version>
    <scope>provided</scope>
</dependency>

没有hadoop环境时可以用此依赖代替

复制代码
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-shaded-hadoop-3</artifactId>
    <version>${hadoop_version}</version>
    <scope>provided</scope>
</dependency>
hive-exec

hive的依赖,此依赖应该放在flink-shaded-hadoop后面,让工程优先访问flink-shaded-hadoop的依赖

复制代码
<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>${hive.version}</version>
    <exclusions>
    <!-- remove conflict dependencies -->
    <exclusion>
            <groupId>org.apache.calcite</groupId>
            <artifactId>calcite-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.calcite</groupId>
            <artifactId>calcite-druid</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.calcite.avatica</groupId>
            <artifactId>avatica</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.calcite</groupId>
            <artifactId>calcite-avatica</artifactId>
        </exclusion>
    </exclusions>
    <scope>provided</scope>
</dependency>
思路

dataStream转为flink table,再通过hive catalog写入到hive表中

写入到hive非分区表
复制代码
val streamEnv = ...
val dataStream = ...
val streamTableEnv = ...
streamTableEnv.createTemporaryView("自定义catalog表名", dataStream, *fields) # 当前flink存在bug,转换时必须指定fields或者schema,否则watermark无法流入table
val catalog = ...
streamTableEnv.registerCatalog("hive", catalog)
streamTableEnv.useCatalog("hive")
streamTableEnv.executeSql("insert sql").print()
写入到hive分区表
  1. streamEnv需要开启checkpoint,保证flink写入hive分区表的写入一致性
  2. hive表ddl中需要指定以下TBLPROPERTIES:
  • sink.partition-commit.trigger:分区提交触发器,单选,可选值为partition-time、process-time(默认), 其中==partition-time需要根据当前数据的watermark来判断分区是否需要提交,当watermark + delay大于等于分区上的时间时就会提交该分区元数据==;process-time的话根据当前系统处理时间来判断分区是否需要提交,当系统处理时间大于等于分区上的时间就会提交该分区元数据

  • partition.time-extractor.timestamp-pattern:使用partition-time触发器时使用该配置项。表示从表字段中提取出表达某个分区的时间的格式,==需要提取到的时间必须为yyyy-MM-dd HH:mm:ss的格式==。比如字段dt的格式为yyyy-MM-dd,则配置为$dt 00:00:00则表示分区时间取值为dt的value的0点0分0秒,可以选择多个表字段组合。当表字段无法抽取出符合的格式时,则使用自定义提取器partition.time-extractor.class。

  • sink.partition-commit.delay: 表示watermark允许event time的最大乱序时间,使用partition-time触发器时可以使用,默认为0s

  • sink.partition-commit.policy.kind:分区提交方式,多选,可选值为metastore、success-file、custom,metastore表示写入元数据库,success-file表示往hdfs分区目录写入一个标志文件,custom表示使用自定义提交方式,通常使用metastore,success-file组合

  • partition.time-extractor.kind:当要使用自定义分区时间提取器时需要配置此项,值配置为custom

  • partition.time-extractor.class:当要使用自定义分区时间提取器时需要配置此项,值配置为自定义提取器的类路径。在集群中运行时,需要把该类打成jar包放到flink lib目录下。

  • 某个分区触发提交后,后续再有此分区的数据进来,仍然会写入hive该分区。

    按process-time触发分区提交

    hive表ddl

    create table xxx(...)
    partitioned by(...)
    stored as orc
    tblproperties(
    'sink.partition-commit.trigger' = 'process-time',
    'sink.partition-commit.policy.kind'='metastore,success-file'
    )

    flink code

    val streamEnv = ...
    streamEnv.enableCheckpointing(...)
    val dataStream = ...
    val streamTableEnv = ...
    streamTableEnv.createTemporaryView("自定义catalog表名", dataStream)
    val catalog = ...
    streamTableEnv.registerCatalog("hive", catalog)
    streamTableEnv.useCatalog("hive")
    streamTableEnv.executeSql("insert sql").print()

    按partition-time触发分区提交

    hive表ddl, 使用默认分区时间提取器

    create table xxx(...)
    partitioned by(...)
    stored as orc
    tblproperties(
    'sink.partition-commit.trigger' = 'partition-time',
    'sink.partition-commit.policy.kind'='metastore,success-file',
    'partition.time-extractor.timestamp-pattern' = ...,
    'sink.partition-commit.delay' = ...,
    )

    flink code

    val streamEnv = ...
    streamEnv.enableCheckpointing(...)
    val dataStream = ... # 已添加watermark
    val streamTableEnv = ...
    streamTableEnv.createTemporaryView("自定义catalog表名", dataStream)
    val catalog = ...
    streamTableEnv.registerCatalog("hive", catalog)
    streamTableEnv.useCatalog("hive")
    streamTableEnv.executeSql("insert sql").print()

    按partition-time触发分区提交

    hive表ddl, 使用自定义分区时间提取器

    create table xxx(...)
    partitioned by(...)
    stored as orc
    tblproperties(
    'sink.partition-commit.trigger' = 'partition-time',
    'sink.partition-commit.policy.kind'='metastore,success-file',
    'partition.time-extractor.timestamp-pattern' = ...,
    'sink.partition-commit.delay' = ...,
    'partition.time-extractor.kind' = 'custom',
    'partition.time-extractor.class' = '自定义分区时间提取器类路径'
    )

    flink code

    以下自定义提取器实现从时间戳中提取出LocalDateTime,以符合partition.time-extractor的yyyy-MM-dd HH:mm:ss的格式要求

    class ExtractPartitionTimeFromUnixTimeStamp extends PartitionTimeExtractor {
    # 参数curPartitionValueList对应的是待作为分区时间提取的表分区字段中某个分区的值,每个分区都会调用一次此函数用来提取分区时间,来判断是否达到提交分区的条件
    # ConvertTimestampToDateTimeFunc返回的格式为yyyy-MM-dd HH:mm:ss的字符串
    # extract返回的LocalDateTime格式需要与分区粒度配合,例如按天分区时,LocalDateTime.parse中的参数格式可以为yyyy-MM-dd 00:00:00
    override def extract(curPartitionKeyList: util.List[String], curPartitionValueList: util.List[String]): LocalDateTime = {
    LocalDateTime.parse(ConvertTimestampToDateTimeFunc(curPartitionValueList.get(0)))
    }
    }

    val streamEnv = ...
    streamEnv.enableCheckpointing(...)
    val dataStream = ... # 已添加watermark
    val streamTableEnv = ...
    streamTableEnv.createTemporaryView("自定义catalog表名", dataStream)
    val catalog = ...
    streamTableEnv.registerCatalog("hive", catalog)
    streamTableEnv.useCatalog("hive")
    streamTableEnv.executeSql("insert sql").print()

相关推荐
云边云科技_云网融合3 分钟前
金融医疗混合云组网如何满足数据安全与合规要求?
大数据·人工智能·物联网
hzcj88810 分钟前
汇正财经:出海数据向好,创新药热度高
大数据·人工智能
Bzc11456231 小时前
中医辨证调护:慢病视角下的血糖健康养护思路
大数据·人工智能·生活
Fluxart.ai1 小时前
2026电商AI出图质量验收标准与质检SOP完整教程
大数据·人工智能
泛普软件1 小时前
工程施工项目管理办公系统能解决哪些现场管理难题与超支问题
大数据·人工智能·软件需求
用户3610588626121 小时前
Spark 核心之广播变量、累加器原理深度剖析
大数据·spark
A15362552 小时前
WMS 仓储系统的软件有哪些?2026 主流产品分类与选型参考
大数据·人工智能
hopsky2 小时前
《HBase 权威指南》 Lars George
大数据·数据库·hbase
Elastic 中国社区官方博客2 小时前
Elasticsearch:列式索引模式 - Columnar index mode
大数据·数据库·elasticsearch·搜索引擎·全文检索
渣渣盟3 小时前
当 Redis 写入不再是瓶颈后,Flink 任务的反压可能来自哪里?如何系统性地定位和解决 Flink 反压问题?
数据库·redis·flink