MySQL到MRS Hudi参数调优
源端优化
MySQL抽取优化。
可通过在作业任务配置参数单击中“添加自定义属性”来新增MySQL同步参数。

可使用的调优参数具体如下:
参数名 |
类型 |
默认值 |
说明 |
---|---|---|---|
scan.incremental.snapshot.backfill.skip |
boolean |
true |
全量阶段是否跳过读取Binlog数据,默认为true。跳过读取Binlog数据可以有效降低内存使用。需要注意的是,跳过读取Binlog功能只提供at-least-once保证。 |
scan.incremental.snapshot.chunk.size |
int |
50000 |
分片大小,决定了全量阶段单个分片最大数据的数据条数以及分片个数。分片大小越大,单个分片数据条数越多,分片个数越小。 当表的条数过多时,作业会划分较多的分片,从而占用过多的内存导致内存问题,请根据表的条数适当调整该值。 当scan.incremental.snapshot.backfill.skip为false时,实时处理集成作业会缓存单个分片的数据,此时分片越大,占用内存越多,引发内存溢出,在此场景下,可以考虑降低分片大小。 |
scan.snapshot.fetch.size |
int |
1024 |
全量阶段抽取数据时,从Mysql侧单次请求抽取数据的最大条数,适当增加请求条数可以减少对Mysql的请求次数提升性能。 |
debezium.max.queue.size |
int |
8192 |
数据缓存队列条数,默认为8192,当源表中单条数据过大时(如1MB),缓存过多数据会导致内存溢出,可以考虑减小该值。 |
debezium.max.queue.size.in.bytes |
int |
0 |
数据缓存队列大小,默认为0,即表示缓存队列不考虑数据大小,只按照数据条数计算。在debezium.max.queue.size无法有效限制内存占用时,考虑显式设置该值来限制缓存数据的大小。 |
jdbc.properties.socketTimeout |
int |
300000 |
全量阶段连接Mysql的socket超时时间,默认为5分钟。当Mysql负载较高,作业出现SocketTimeout异常时,考虑增大该值。 |
jdbc.properties.connectTimeout |
int |
60000 |
全量阶段连接Mysql的连接超时时间,默认为1分钟。当Mysql负载较高,作业出现ConnectTimeout异常时,考虑增大该值。 |
参数名 |
类型 |
默认值 |
说明 |
---|---|---|---|
debezium.max.queue.size |
int |
8192 |
数据缓存队列条数,默认为8192,当源表中单条数据过大时(如1MB),缓存过多数据会导致内存溢出,可以考虑减小该值。 |
debezium.max.queue.size.in.bytes |
int |
0 |
数据缓存队列大小,默认为0,即表示缓存队列不考虑数据大小,只按照数据条数计算。在debezium.max.queue.size无法有效限制内存占用时,考虑显式设置该值来限制缓存数据的大小。 |
目的端优化
Hudi写入优化。
Hudi表写入性能慢,优先审视表设计是否合理,建议使用Hudi Bucket索引的MOR表,并根据实际数据量配置Bucket桶数,以达到Migration写入性能最佳。

- 使用Bucket索引:通过在“Hudi表属性全局配置”或在映射后的单表“表属性编辑”中配置index.type和hoodie.bucket.index.num.buckets属性可进行配置。
- 判断使用分区表还是非分区表。
- 事实表通常整表数据规模较大,以新增数据为主,更新数据占比小,且更新数据大多落在近一段时间范围内(年或月或天),下游读取该表进行ETL计算时通常会使用时间范围进行裁剪(例如最近一天、一月、一年),这种表通常可以通过数据的创建时间来做分区以保证最佳读写性能。
- 维度表数据量一般整表数据规模较小,以更新数据为主,新增较少,表数据量比较稳定,且读取时通常需要全量读取做join之类的ETL计算,因此通常使用非分区表性能更好。
- 确认表内桶数。
使用Hudi BUCKET表时需要设置Bucket桶数,桶数设置关系到表的性能,需要格外引起注意。
- 非分区表桶数 = MAX(CEIL(单表数据量大小(GB)/1GB), 4)。
- 分区表桶数 = MAX(CEIL(单分区数据量大小(GB)/1GB), 1)。
其中,要注意的是:
- 需要使用的是表的总数据大小,而不是压缩以后的文件大小。
- 桶的设置以偶数最佳,非分区表最小桶数请设置4个,分区表最小桶数请设置1个。
同时,可通过在Hudi的目的端配置中单击“Hudi表属性全局配置”或在映射后的单表“表属性编辑”中,添加优化参数。

参数名 |
类型 |
默认值 |
说明 |
---|---|---|---|
hoodie.sink.flush.tasks |
int |
1 |
Hudi flush数据时的并发数,默认为1,即顺序写入。当Hud单次commit涉及FleGroup较多时(如源端表较多更新历史数据的场景),考虑增大该值。 已知单线程flush的FileGroup的数据 = 单次Commit的FileGroup数量 / 作业并发数。 单线程flush的FileGroup的数量 <= 5,推荐值2。 单线程flush的FileGroup的数量 <= 10,推荐值5。 单线程flush的FileGroup的数量 <= 25,推荐值10。 单线程flush的FileGroup的数量 <= 50,推荐值20。 单线程flush的FileGroup的数量 > 50,推荐值30。 flush的并发数越大,flush时内存会相应升高,请结合实时处理集成作业内存监控适当调整该值。 |
hoodie.context.flatmap.parallelism |
int |
1 |
Hudi在commit时,会进行分区扫描操作,默认是单并发操作,当Hudi单次commit涉及的分区较多时,考虑增大该值以提升commit速度。 单次Commit的分区数量 <= 10,推荐值5。 单次Commit的分区数量 <= 25,推荐值10。 单次Commit的分区数量 <= 50,推荐值20。 单次Commit的分区数量 > 50,推荐值30。 |
compaction.async.enabled |
boolean |
true |
是否开启compaction,默认为true,即默认开启hudi的compaction操作。compaction操作一定程度会影响实时任务的写入性能,为了保证Migration作业的稳定性可以考虑设置为false关闭compaction操作,将Hudi Compaction单独拆成Spark作业交由MRS执行,具体可以参考如何配置Hudi Compaction的Spark周期任务?。 |
compaction.delta_commits |
int |
5 |
实时处理集成生成compaction request的频率,默认为5时,即每5次commit生成一个compaction request。compaction request生成频率降低可以使得compaction频率降低从而提升作业性能。如果hudi增量数据较小。可以考虑增大该值。 |
场景分析
降内存
- 减小数据缓存、提高数据flush频率。
Hudi在checkpoint触发时做数据flush,【任务配置】中降低checkpoint周期和最小间隔时间,可以有效控制缓存空间占用。
使用场景:内存占用较高时使用;发现checkpoint.interval配置大于默认值。
使用方式:在任务配置中添加自定义属性。
参数名
默认值
解释
checkpoint.interval
60000
根据实际情况,checkpoint.interval可以下调到30000。
单位ms,触发checkpoint的周期。
min.pause.between.checkpoints.ms
0
单位ms,两次checkpoint之间至少间隔的时间。
图6 checkpoint周期参数配置 - 优化建表。
建表不合理,会导致作业整体内存占用大,建议客户在评估业务影响后按推荐重建表。
使用场景:
- 大表使用BLOOM索。
参数名
默认值
解释
index.type
BLOOM
索引类型,支持BLOOM/BUCKET。强烈建议使用BUCKET索引,Hudi表更加健壮。
hoodie.bucket.index.num.buckets
256
BUCKET索引时生效,单个分区下桶文件(parquet文件)数量。
强烈建议客户使用BUCKET索引,可以在【Hudi表全局属性】或【表属性编辑】中添加如下配置完成Hudi自动建表。
- 分区表BUCKET索引桶数量配置过大。
分区表hoodie.bucket.index.num.buckets参数配置过大会导致单次flush数据写出的文件数量过多,会占用较多内存。
taskmanager日志搜索关键字“bucket number”可以查看到单次flush数据写出文件数量,大于100时内存占用和写出效率都会相应降低,需要考虑降低表的桶文件数量。
图7 单次flush桶文件数量过多场景日志建议客户根据实际的数据场景估算桶数据量,详情请参考表8,建议对非分区表hoodie.bucket.index.num.buckets参数控制在10以内。
- 大表使用BLOOM索。
- 作业减负。
Hudi需要定期完成compaction、clean和archive动作,如果在实时作业中完成这些任务会消耗大量的内存资源,建议拆分成独立的compaction作业。
- 使用场景:客户在作业中配置的为在线compaction、clean、archive,如果没有配置任何参数,默认也为在线compaction。
图8 配置实时作业的compaction、clean、archive参数
- 使用方式:关闭/ 取消实时作业compaction、clean、archive。
图9 关闭/ 取消实时作业的compaction、clean、archive
同时参考参考如何配置Hudi Compaction的Spark周期任务?手动配置离线compaction作业。
- 使用场景:客户在作业中配置的为在线compaction、clean、archive,如果没有配置任何参数,默认也为在线compaction。
- 限流。
- 使用场景:客户对同步时延无强制要求,且希望作业能够避过数据高峰,稳定运行。
- 使用方式:在Hudi目的端参数配置中添加以下参数。
参数名
默认值
解释
write.rate.limit
无限制
单位:条/s
Hudi支持对同步速率限制,但可能会引起作业时延,谨慎使用。
- 增加taskmanager堆内存。
Migration默认1并发配置4G内存,扩展单个并发的可用内存可以通过以下表4 任务配置调优。
表4 【任务配置】中添加自定义参数 参数名
默认值
解释
taskmanager.memory.process.size
4G
taskmanager堆内存大小。
taskmanager.memory.managed.fraction
0.2
管理内存,建议配置为0。
修改Migration单个并发的内存配置会导致资源组的使用率统计不正确,谨慎使用。
降反压
- 加大实时作业并发,提高数据写出效率。
写Hudi表默认按照数据主键并发写,在【任务配置】加到作业并发数可以有效加快数据落盘到表目录。
- 增加单个taskmanager内并发线程。
参数名
默认值
解释
hoodie.sink.flush.tasks
2
配置单个作业并发内,flush数据的线程数量。加大线程数会导致内存使用上涨,不建议配置超过40。
每个taskmanager内会启动线程池按照Hudi桶ID并发写数据文件,默认线程数为2。
典型使用场景:
图10 CPU使用率低Taskmanager日志搜索关键字“bucket number”可以看到每次flush数据需要写出的文件数量:
图11 单批次需要flush的数据文件过多发现单次flush需要写出的文件数量超过100个,说明IO已经成为瓶颈,需要加大flush并发落盘数据文件。
参数配置方式:在Hudi全局配置或表属性配置中配置。图12 Hudi高级参数配置方式表5 单次flush需要的线程数 表类型
推荐值
rt表(非分区表)
5
dsy表(年分区)
10
dsm表(月份区)
20
ds表(日分区)
40
参考日志查询结果估算单次flush需要的线程数,也可以通过如下配置方案(前提是内存充足的情况下)进行配置:
Hudi在做compaction计划时会做全表扫描,查找需要合并的log文件,通过添加hoodie.context.flatmap.parallelism参数将全表扫描的过程并发起来,缩短Hudi commit阶段的时长,提高数据写出效率。
表6 推荐配置 表类型
推荐值
rt表(非分区表)
10
dsy表(年分区)
10
dsm表(月份区)
25
ds表(日分区)
50
- 合理建表(重建表)。
当客户使用BUCKET索引时,如果hoodie.bucket.index.num.buckets数量配置过少,会导致作业并发利用不起来,影响同步效率。
现象:搜索关键日志“bucket number”,显示每次flush数据只写出几个数据文件,且数据量较大,且添加作业并发或者flush线程数无法提升性能。
需要评估业务,必要时对Hudi表重建,扩大hoodie.bucket.index.num.buckets参数值,让分区目录下分桶数量增加。
- 清理Hudi timeline(.hoodie目录下文件)。
实时写Hudi需要定期扫描Hudi表元数据目录(.hoodie目录),如果.hoodie目录下commit文件长时间不进行archive会导致扫描过程非常慢(list OBS操作),最终影响写出效率。
现象:时延上涨,数据同步速率非常慢只能达到几百条每秒,但是按压达到100,查看对应Hudi表元数据目录下commit文件数量达到几千甚至上万个。
图13 Hudi表commit元数据过多需要及时调整archive参数,减少保留的commit文件数量,建议保留的commit文件不超过4000个。
set hoodie.keep.min.commits = 1830;
set hoodie.keep.max.commits = 1840;
- 降低数据flush频率,减少IO消耗。
在Hudi on OBS的场景,flush数据到OBS、扫描.hoodie目录都存在大量的IO消耗,为了减少IO交互的频率,避免重复的list OBS动作,可以延长作业的checkpoint周期,让缓存的数据量更多再进行flush。
在【任务配置】中添加如下自定义参数,扩大checkpoint周期。
参数名
默认值
解释
checkpoint.interval
60000
单位ms,触发checkpoint的周期。
min.pause.between.checkpoints.ms
0
单位ms,两次checkpoint之间至少间隔的时间。
checkpoint.timeout.ms
6000000
默认10min,checkpoint执行超时时间。
checkpoint.interval可以扩大到300000(5min),需要同步扩大作业并发以减小内存压力,同时需要扩大checkpoint.timeout.ms到1800000以防止checkpoint超时。