
# MySQL到MRS Hudi参数调优
#### 源端优化
MySQL抽取优化。
可通过在作业任务配置参数单击中"添加自定义属性"来新增MySQL同步参数。
图1添加自定义属性   
![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002096006468.png "点击放大")
可使用的调优参数具体如下：
表1全量阶段优化参数 
| 参数名                                     | 类型      | 默认值    | 说明                                                                                                                                                                                                                                                                                                    |
|:---|:---|:---|:---|
| 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异常时，考虑增大该值。                                                                                                                                                                                                                                    |
   
表2增量阶段优化参数 
| 参数名                              | 类型  | 默认值  | 说明                                                                                             |
|:---|:---|:---|:---|
| 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写入性能最佳。
![](https://support.huaweicloud.com/usermanual-dataartsstudio/public_sys-resources/note_3.0-zh-cn.png)
- 使用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表属性全局配置"或在映射后的单表"表属性编辑"中，添加优化参数。
图2添加自定义属性   
![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002095860442.png "点击放大")
表3Hudi写入优化参数 
| 参数名                                | 类型      | 默认值  | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
|:---|:---|:---|:---|
| hoodie.sink.flush.tasks            | int     | 1    | Hudi flush数据时的并发数，默认为1，即顺序写入。当Hudi单次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周期任务？](https://support.huaweicloud.com/dataartsstudio_faq/dataartsstudio_03_7597.html)。                                                                                                                                                                                                                                                                                                                                                                                       |
| compaction.delta_commits           | int     | 5    | 实时处理集成生成compaction request的频率，默认为5时，即每5次commit生成一个compaction request。compaction request生成频率降低可以使得compaction频率降低从而提升作业性能。如果hudi增量数据较小。可以考虑增大该值。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   
#### 场景分析
在分析完监控指标与日志后可以确认调优场景，以下介绍写Hudi时针对不同调优场景如何使用参数调优：
- **降内存**
  图3MySQL \> MRS Hudi内存调优方案   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369048917.png "点击放大")
  - [减小数据缓存、提高数据flush频率。]
  
  - [优化建表。]
  
  - [作业减负。]
  
  - [限流。]
  
  - [增加taskmanager堆内存。]
   
- **降反压**
  图4MySQL \> MRS Hudi反压调优方案   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002368890509.png "点击放大")
  - [加大实时作业并发，提高数据写出效率。]
  
  - [增加单个taskmanager内并发线程。]
  
  - [合理建表（重建表）。]
  
  - [清理Hudi timeline（.hoodie目录下文件）。]
  
  - [降低数据flush频率，减少IO消耗。]
   
- **源端binlog激增（无反压）**
  图5源端binlog激增（无反压）场景解决方案   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369051105.png "点击放大")
  源端binlog文件激增时，需要及时：
  - 调大实时作业并发，避免目的端写出成为瓶颈，反压源端抽取。
  
  - 调大taskmanager堆内存，避免数据量过大时打爆作业。 在任务配置中添加参数：
    taskmanager.memory.managed.fraction = 0（默认0.2）
    taskmanager.memory.process.size = 4G（默认不足4G）
    
  
  - 必要时果断将时延较大的表从实时作业中拆分出去，通过离线迁移完成大表的数据迁移。
   
 
#### **降内存**
- **减小数据缓存、提高数据flush频率。**
  Hudi在checkpoint触发时做数据flush，【任务配置】中降低checkpoint周期和最小间隔时间，可以有效控制缓存空间占用。
  使用场景：内存占用较高时使用；发现checkpoint.interval配置大于默认值。
  使用方式：在任务配置中添加自定义属性。
  表4添加自定义属性 
  | 参数名                              | 默认值                                                                                 | 解释                          |
  |:---|:---|:---|
  | checkpoint.interval              | 60000 根据实际情况，checkpoint.interval可以下调到30000。 | 单位ms，触发checkpoint的周期。       |
  | min.pause.between.checkpoints.ms | 0                                                                                   | 单位ms，两次checkpoint之间至少间隔的时间。 |
     
  图6checkpoint周期参数配置   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369002757.png "点击放大") 
- **优化建表** **。**
  建表不合理，会导致作业整体内存占用大，建议客户在评估业务影响后按推荐重建表。
  使用场景：
  - 大表使用BLOOM索。
    表5配置参数 
    | 参数名                             | 默认值   | 解释                                            |
    |:---|:---|:---|
    | 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桶文件数量过多场景日志   
    ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369162617.png "点击放大")
    建议客户根据实际的数据场景估算桶数据量，详情请参考[表8](https://support.huaweicloud.com/usermanual-dataartsstudio/dataartsstudio_01_7668.html#dataartsstudio_01_7668__table37371623173319)，建议对非分区表hoodie.bucket.index.num.buckets参数控制在10以内。
    
   
- **作业减负。**
  Hudi需要定期完成compaction、clean和archive动作，如果在实时作业中完成这些任务会消耗大量的内存资源，建议拆分成独立的compaction作业。
  - 使用场景：客户在作业中配置的为在线compaction、clean、archive，如果没有配置任何参数，默认也为在线compaction。
    图8配置实时作业的compaction、clean、archive参数   
    ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002335324370.png "点击放大") 
  
  - 使用方式：关闭/ 取消实时作业compaction、clean、archive。
    图9关闭/ 取消实时作业的compaction、clean、archive   
    ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002335164606.png "点击放大") 
  
  
  同时参考[如何配置Hudi Compaction的Spark周期任务？](https://support.huaweicloud.com/dataartsstudio_faq/dataartsstudio_03_7597.html)手动配置离线compaction作业。
  
- **限流** 。
  - 使用场景：客户对同步时延无强制要求，且希望作业能够避过数据高峰，稳定运行。
  
  - 使用方式：在Hudi目的端参数配置中添加以下参数。
    表6Hudi目的端参数配置 
    | 参数名              | 默认值 | 解释     |
    |:---|:---|:---|
    | write.rate.limit | 无限制 | 单位：条/s |
       
    Hudi支持对同步速率限制，但可能会引起作业时延，谨慎使用。
    
   
- **增加taskmanager堆内存** 。
  Migration默认1并发配置4G内存，扩展单个并发的可用内存可以通过以下[表4 任务配置]调优。
   表7【任务配置】中添加自定义参数 
  | 参数名                                 | 默认值 | 解释                |
  |:---|:---|:---|
  | taskmanager.memory.process.size     | 4G  | taskmanager堆内存大小。 |
  | taskmanager.memory.managed.fraction | 0.2 | 管理内存，建议配置为0。      |
     
  修改Migration单个并发的内存配置会导致资源组的使用率统计不正确，谨慎使用。
  
 
#### **降反压**
- **加大实时作业并发，提高数据写出效率** 。
  写Hudi表默认按照数据主键并发写，在【任务配置】加到作业并发数可以有效加快数据落盘到表目录。
  
- **增加单个taskmanager内并发线程** 。
  表8配置flush 
  | **参数名**                 | **默认值** | **解释**                                           |
  |:---|:---|:---|
  | hoodie.sink.flush.tasks | 2       | 配置单个作业并发内，flush数据的线程数量。加大线程数会导致内存使用上涨，不建议配置超过40。 |
     
  每个taskmanager内会启动线程池按照Hudi桶ID并发写数据文件，默认线程数为2。
  典型使用场景：
  图10CPU使用率低   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369002777.png "点击放大")
  Taskmanager日志搜索关键字"bucket number"可以看到每次flush数据需要写出的文件数量：
  图11单批次需要flush的数据文件过多   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002369162641.png "点击放大")
  发现单次flush需要写出的文件数量超过100个，说明IO已经成为瓶颈，需要加大flush并发落盘数据文件。
  参数配置方式：在Hudi全局配置或表属性配置中配置。
  图12Hudi高级参数配置方式   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002335324394.png "点击放大")
  表9单次flush需要的线程数 
  | 表类型       | 推荐值 |
  |:---|:---|
  | rt表（非分区表） | 5   |
  | dsy表（年分区） | 10  |
  | dsm表（月份区） | 20  |
  | ds表（日分区）  | 40  |
     
  参考日志查询结果估算单次flush需要的线程数，也可以通过如下配置方案（前提是内存充足的情况下）进行配置：
  Hudi在做compaction计划时会做全表扫描，查找需要合并的log文件，通过添加**hoodie.context.flatmap.parallelism**参数将全表扫描的过程并发起来，缩短Hudi commit阶段的时长，提高数据写出效率。
  表10推荐配置 
  | 表类型       | 推荐值 |
  |:---|:---|
  | 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文件数量达到几千甚至上万个。
  图13Hudi表commit元数据过多   
  ![](https://support.huaweicloud.com/usermanual-dataartsstudio/zh-cn_image_0000002335164614.png "点击放大")
  需要及时调整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周期。
  表11添加自定义参数 
  | 参数名                              | 默认值     | 解释                          |
  |:---|:---|:---|
  | 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超时。
  
 
