HUDI-0.11.0 BUCKET index on Flink 新特性试用

1.背景

在0.10.1版本下,用默认的index(FLINK_STATE),在upsert的模式下,几十亿级别的数据更新会很消耗内存以及ckp时过长,因此切换到0.11.0的BUCKET索引;
仅对于当前环境:flink1.13.2 + hudi 0.11.0-(master 2022.04.11) + cow + hdfs;

关键配置项:'index.type' = 'BUCKET', 'hoodie.bucket.index.num.buckets' = '256'

2.BUCKET与FLINK_STATE的区别

FLINK_STATE: 简单的说,hudi的upsert模式需要指定主键组,更新时是按照主键进行更新的,而数据是存在于hdfs文件上的,那么主键与文件名的映射就是必须的 => 依托Flink特性,存在state里面;因此程序第一次加载hudi表的历史数据时,需要设置 'index.bootstrap.enabled' = 'true' 来加载历史数据到state里,更新可以跨分区;

BUCKET:简单的说,就是”基于文件的分桶“,比如设置主键为id,桶个数256('hoodie.bucket.index.num.buckets' = '256'),那么计算bucket序号的方法就是(id.hashCode() & Integer.MAX_VALUE) % 256;
而且一旦设置,桶(buckets)的个数是不能变的,对应文件个数是不变的 => 预估数据量来保证合理的文件数量与大小,减少小文件或过度写放大(因为文件个数不变,单个文件大小会一直增大);优点:无内存(仅指flink|Managed Memory)占用,缺点:文件IO带来cpu压力会升高;
BUCKET是基于单个文件的设置,因此不能跨分区;
tips:bucket个数预估可以使用离线导数据看hdfs文件大小来预估;
总结:FLINK_STATE占内存,初始化加载历史数据慢,可跨分区;BUCKET占磁盘,不可跨分区,省内存;

3.相关配置

flink实时流配置

  'connector' = 'hudi',
  'path' = 'hdfs://path/',
  'index.type' = 'BUCKET',                 -- bucket索引
  'hoodie.parquet.compression.codec'= 'snappy',
  'table.type' = 'COPY_ON_WRITE',
  'write.operation' = 'upsert', 
  'write.task.max.size' = '2048', 
  'write.precombine' = 'true',
  'write.precombine.field' = 'update_time',
  'write.tasks' = '6',
  'write.bucket_assign.tasks' = '6',
  'hoodie.bucket.index.hash.field' = 'id',         -- 主键
  'hoodie.bucket.index.num.buckets' = '256',  -- 桶个数
  'hive_sync.enable'='true',
  'hive_sync.table'='TABLE_NAME',
  'hive_sync.db'='DB_NAME',
  'hive_sync.mode' = 'hms',
  'hive_sync.metastore.uris' = 'thrift://HOST:9083',
  'hive_sync.skip_ro_suffix' = 'true',
  'write.insert.cluster' = 'true',
  'write.ignore.failed' = 'true',
  'clean.async.enabled' = 'true',
  'clean.retain_commits' = '3', 
  'hoodie.cleaner.commits.retained' = '3',
  'hoodie.keep.min.commits' = '4', 
  'hoodie.keep.max.commits' = '8'

Flink离线导入数据配置

 'connector' = 'hudi',
  'path' = 'hdfs://PATH',
  'hoodie.parquet.compression.codec'= 'snappy',
  'index.type' = 'BUCKET',
  'table.type' = 'COPY_ON_WRITE',
  'write.operation' = 'bulk_insert', 
  'write.tasks' = '2', 
  'hoodie.bucket.index.num.buckets' = '256', 
  'hoodie.bucket.index.hash.field' = 'id' 

离线导入完成后,观察hdfs文件前八位为数字,例如00000000-,00000255-,即设置成功,然后可直接接入实时数据;
注意:从hive导数据到hudi,可以调整一下hive source的并行度

tableConfig.setInteger(HiveOptions.TABLE_EXEC_HIVE_INFER_SOURCE_PARALLELISM_MAX, source_parallelism_max)

4.性能小结

实时情况:基于目前的数据量,单文件(80M)操作在100ms左右:eg: block read in memory in 171 ms. row count = 617384,十几张表每次ckp三四分钟左右,对于我们十几分钟的ckp来说可以接受;

离线导数据情况:对于亿级别数据的离线导入,资源不算大,十几分钟就导入完成了;

:如果ckp设置太小,cow表情况下,频繁操作bucket文件,会对集群cpu load产生压力;

posted @ 2022-04-07 21:03  magic_guan  阅读(1382)  评论(3编辑  收藏  举报