Flink-Hudi技术实践:Insert场景开发实践

0 阅读6分钟

一、背景介绍   

Hudi提供了两种核心表类型:写时复制表(COW)与读时合并表(MOR)。前者仅使用列式存储格式(Parquet)存储数据,即使只更新少量记录,也可能需要重写整个文件,导致写放大,适用于读多写少的场景(读负载高);后者使用列存+行存格式(Parquet+Avro)存储数据,更新操作以追加方式写入轻量级的日志文件,适用于写多读少的场景(写负载高)。   

Hudi支持多种写操作,通过 hoodie.datasource.write.operation参数指定。

  • Upsert(插入/更新):默认且最常用的操作。适用于源数据包含更新的场景,如CDC数据。
  • Insert(插入):纯插入操作,适用于来源为只追加(append-only)数据的场景,如日志、事件流。
  • Bulk Insert(批量插入):专为初始数据集批量加载设计,仅用于初始化。

    在Flink+Hudi的实时入湖场景下,我们使用Hudi-Mor表承载数据的准实时写入,根据数据特性与业务要求选择Upsert或Insert操作类型实现数据的更新与追加。今天文章聚焦在Hudi-Insert操作场景,介绍Insert模式的的技术原理、适用场景、关键参数与最佳实践,提供一套可落地的开发实践指南。

二、Hudi-Insert技术特性与适用场景

1.Hudi-Insert技术特性   

在 Hudi 中,Insert模式的核心特征是追加写入。当 Flink 任务以 Insert模式向 MOR 表写入数据时,每条记录都会被作为一条全新的、独立的记录写入表,不涉及主键查找、去重或更新操作。

  • 纯追加写入:写入过程不触发任何主键匹配、索引查找操作,直接将数据写入 Hudi MOR 表的日志文件(Log File),写入延迟极低,吞吐极高。
  • 主键无约束:允许重复主键写入,适合不需要去重的日志类数据,避免了 upsert模式的索引维护开销。
  • MOR 表原生适配:完美适配 Hudi MOR 表的增量写入特性,支持实时增量查询、流批一体分析。
  • 小文件问题:由于 Flink 每次 checkpoint 都会触发一次写入事务,当数据流量波动时,会产生大量小的 Parquet 数据文件,导致查询 IO 次数激增、性能下降,因此必须配套 Clustering 治理。

2.Hudi-Insert适用场景   

基于 Insert模式的技术特性,其典型应用场景包括:

  • 仅追加的日志或数据

    例如用户点击流、系统事件日志、IoT设备上报数据等。这类数据生成后不再变更,无需基于主键去重,Insert模式可以高效地完成写入。

  • 历史数据批量导入

    在进行数据湖初始化时,使用 Insert或Spark的Bulk Insert模式,可以快速将大量历史数据写入 Hudi 表,避免在数据导入阶段产生不必要的开销。

  • 变更日志(Changelog)保留

    对于需要保留数据变更历史、支持溯源分析的场景,Insert模式可以完整保留每次数据变更的记录,即使同一主键发生多次更新,其历史状态也会被完整保留。

三、Hudi-Insert参数配置指南

1.Flink-Hudi表基础with参数

'connector' = 'hudi'
'table.type' = 'MERGE_ON_READ'
'path' = ''
'write.operation' = 'insert'
'hoodie.datasource.write.recordkey.field' = ''
'hoodie.datasource.write.partitionpath.field' = ''
'metadata.enabled' = 'false'
'hive_sync.enable' = 'true'
'hive_sync.db' = ''
'hive_sync.table' = ''
'hive_sync.mode' = 'hms'
'hive_sync.metastore.uris' = ''
'hive_sync.table.strategy' = 'RT'
'hoodie.datasource.write.hive_style_partitioning' = 'true'

按官方推荐,FLink-Hudi作业的checkpoint间隔设置为2-5分钟,其他自定义参数可参阅Hudi官网(hudi.apache.org/docs/1.0.2/…

2.Clustering介绍

在 Flink 写入 Hudi MOR 表的过程中,小文件问题是最常见的挑战之一。在0.13.1版本以前,对于Hudi MOR表的流式写入,Flink 每次 Checkpoint 都会触发一次写入事务并生成Avro的log文件,由配置的Compaction服务完成小文件合并。自0.13.1版本起,通过HUDI-6045的改进,MOR表的 insert操作被统一为走“Append写流程”。这意味着,在流式写入场景下,只要写操作类型指定为 insert,数据就会像bulk_insert一样,直接通过BulkInsertWriterHelper生成新的Parquet基础文件,而不再经过写Log的路径。

Clustering(聚类)是 Hudi 提供的小文件治理服务,核心逻辑是:定期将多个小文件(仅限parquet文件)合并为大文件,优化文件布局,提升查询性能。根据执行方式,Clustering 分为在线聚类和离线聚类两种方案。其中Clustering核心参数说明如下:

参数名默认值说明
clustering.async.enabledfalse是否异步执行 clustering plan,默认关闭;在线聚类需设为 true,离线聚类设为 false
clustering.schedule.enabledfalse是否在写入时异步调度 clustering plan,默认关闭;在线 / 离线聚类均需设为 true
clustering.tasks4Clustering task 执行并发数
clustering.delta_commits4调度 clustering plan 的间隔 commits,clustering.schedule.enabled=true时生效
clustering.plan.strategy.small.file.limit600MB小于该大小的文件才会参与 clustering,默认 600MB
clustering.plan.strategy.target.file.max.bytes1GB1024*1024*1024Clustering 单文件目标大小,默认 1GB
clustering.plan.strategy.sort.columnsN/A支持指定特殊的排序字段,用于聚类时排序(如按时间字段排序优化查询)
clustering.plan.partition.filter.modeNONE分区过滤模式:- NONE:不做限制- RECENT_DAYS:按时间(天)回溯- SELECTED_PARTITIONS:指定固定的 partition
clustering.plan.strategy.daybased.lookback.partitions2RECENT_DAYS生效,默认 2 天(回溯最近 2 天的分区)

3.在线/离线Clustering实践

为保障Hudi表数据查询性能,我们以20min内完成Clustering为目标,在内部展开多场景压测验证(数据大小、字段数、TPS、资源规格等),最后制定了一个Clustering策略选型的参考原则:

  • checkpoint 间隔 120s
  • 单条数据大小 1kb
  • 表字段数 60
  • parquet 文件大小推荐 0.3g~1g,最大不超过 2g

若上游Kafka的写入TPS在8000以下,选择在线Clustering,否则选择离线Clustering。以下为不同TPS下增加的作业配置:

TPSFlink TM资源写入配置
30002c4g'clustering.schedule.enabled'='true',-- 启动聚类调度'clustering.async.enabled'='true'-- 异步执行聚类(在线聚类为true,离线为false)'clustering.delta_commits'='10' 'clustering.plan.strategy.small.file.limit'='300' 'clustering.plan.strategy.max.bytes.per.group'='1073741824'
50002c6g'write.parquet.max.file.size'='512' 'clustering.delta_commits'='10' 'clustering.plan.strategy.small.file.limit'='300' 'clustering.plan.strategy.max.bytes.per.group'='1073741824'
70004c12g'write.parquet.max.file.size'='256' 'clustering.delta_commits'='10' 'clustering.plan.strategy.small.file.limit'='300' 'clustering.plan.strategy.max.bytes.per.group'='1073741824'
85003c6g'clustering.schedule.enabled'='true',-- 启动聚类调度'clustering.async.enabled'='false'-- 异步执行聚类(离线聚类为false)'write.parquet.max.file.size'='256' 'clustering.delta_commits'='10' 'clustering.plan.strategy.small.file.limit'='300' 'clustering.plan.strategy.max.bytes.per.group'='1073741824'
100004c12g'write.parquet.max.file.size'='256' 'clustering.delta_commits'='10' 'clustering.plan.strategy.small.file.limit'='300' 'clustering.plan.strategy.max.bytes.per.group'='1073741824'

四、总结展望

本文围绕 Flink 写入 Hudi MOR 表的 Insert模式,系统介绍了其技术特性、适用场景以及关键的 Clustering 配置实践。对于正在构建实时数据湖的团队而言,深入理解 Insert模式的底层机制,并结合实际业务场景进行针对性优化,将是实现高效、稳定数据写入的关键一步。