SQL Hudi 的 clustering 与 compaction 定时任务调度规范

3次阅读

clustering任务卡在pending因需外部调度且满足三前提:启用clustering、存在待聚类小文件、无运行中compaction/clustering;常见误以为配置开启即自动执行。

SQL Hudi 的 clustering 与 compaction 定时任务调度规范

Clustering 任务为什么总卡在 PENDING 状态

因为 Hudi 的 clustering 不是自动触发的,它依赖外部调度器显式提交,且必须满足三个前提:表已启用 clustering(hoodie.clustering.enable=true),存在待聚类的文件组(即有新写入但未重分布的小文件),且当前没有正在运行的 compaction 或 clustering 任务。常见错误是误以为开启配置后会自动跑——其实只是“允许被调度”,不是“自动调度”。

实操建议:

  • 检查 hoodie.clustering.inline 是否为 false(推荐关掉内联,避免阻塞写入)
  • spark sql 查看待聚类计划:DESCRIBE table EXTENDED <db>.<table>,关注 <code>hoodie.clustering.plan.strategy.class 和实际生成的 .hoodie/.aux/clustering/ 下是否有 plan 文件
  • 确认调度器(如 Airflow、DolphinScheduler)提交的是 spark-submit 命令,且含 --conf hoodie.clustering.async.enabled=true 和正确 --class org.apache.hudi.utilities.HoodieClusteringJob
  • Compaction 任务失败报 “Cannot schedule compaction when clustering is running”

    这是 Hudi 0.12+ 的强互斥机制:compaction 和 clustering 共享同一把表级锁(.hoodie/.temp/compaction 目录),哪怕只是 pending 状态的 clustering 计划没清理干净,也会阻塞后续所有 compaction。不是 bug,是设计使然——避免小文件重分布和日志合并同时修改同一文件组。

    实操建议:

    • 先清空残留计划:hdfs dfs -rm -r <base-path>/.hoodie/.aux/clustering/*</base-path>(或对应云存储路径)
    • 查当前锁状态:hdfs dfs -ls <base-path>/.hoodie/.temp/</base-path>,删掉非空的 compaction/clustering 目录
    • 调度时错开时间窗口:比如 clustering 定在凌晨 2 点,compaction 定在凌晨 4 点,中间留至少 30 分钟 buffer
    • 禁用自动 compaction(hoodie.compact.inline=false),全部交由异步任务控制,避免写入链路意外触发

    Airflow 中调度 clustering 任务的 DAG 写法要点

    直接调 spark-submit 最稳,别用 Hudi 自带的 HoodieDeltaStreamer 包裹 clustering——它不支持传 clustering 参数。关键不是“怎么写 DAG”,而是“怎么传参不丢”。

    实操建议:

    • DAG 中用 BashOperatorspark-submit,别用 SparkSubmitOperator(它对 –conf 解析不稳定)
    • 必传参数包括:--conf hoodie.clustering.execute.inline=false--conf hoodie.clustering.target.io.rate.bytes.per.second=50000000(防带宽打满)、--conf hoodie.clustering.max.num.groups=4(控并发
    • --driver-java-options "-Dlog4j2.configurationFile=file:///path/to/log4j2.xml",否则集群日志里看不到 clustering 进度
    • 设置 retries=1,但 retry_delay=timedelta(minutes=5)——clustering 失败多因资源争抢,等几分钟再试更有效

    Clustering 后 Parquet 小文件反而更多了?

    默认策略(org.apache.hudi.client.clustering.plan.strategy.SparkSizeBasedClusteringPlanStrategy)只按大小合并,但若输入文件本身都小于 hoodie.clustering.plan.strategy.target.file.max.bytes(默认 1GB),它就每 3 个文件一组生成一个新文件,结果 100 个小文件 → 34 个中等文件 → 可能还是太多。这不是异常,是策略没配对。

    实操建议:

    • 调低目标文件大小:--conf hoodie.clustering.plan.strategy.target.file.max.bytes=134217728(128MB)
    • 改用时间窗口策略:--conf hoodie.clustering.plan.strategy.class=org.apache.hudi.client.clustering.plan.strategy.SparkRecentDaysClusteringPlanStrategy,配合 --conf hoodie.clustering.plan.strategy.days.with.data=3,只聚最近三天数据,减少跨分区干扰
    • 观察 hoodie.clustering.plan.strategy.sort.columns 是否设了业务主键——没排序的聚类等于白干,小文件物理位置依然散

    真正难的不是跑起来,是每次调整参数后得进 .hoodie/archived/ 翻 commit timeline,确认 clustering commit 类型是 CLUSTER 而不是 COMMIT,否则说明根本没生效。

text=ZqhQzanResources