首先部署Hudi不需要启动任何服务,就只是个安装包而已。实际上就是使用现有的服务器设备构件事务型分布式存储模型。Hudi通过Spark任务创建他的程序,采用Spark标准协议开发(标准协议见:Cluster Mode Overview - Spark 3.4.1 Documentation)。查询Hudi表通过安装在Apache Hive、Apache Spark或PrestoDB中的库完成,因此不需要额外的基础设施。

典型的Hudi数据使用可以在两种模式下实现。在单次运行模式下,Hudi摄取读取下一批数据,将它们摄取到Hudi表并退出。在连续模式下,Hudi摄取作为长时间运行的服务在循环中执行摄取。

对于Merge_On_Read表,Hudi摄取还需要考虑压缩增量文件。同样,可以以异步模式执行压缩,方法是让压缩与摄取同时运行,或者一个接一个地以串行方式运行。 

增量流处理 

DeltaStreamer 是一个独立的实用程序,用于增量地从各种来源(如DFS、Kafka和DB changlogs)中提取上游更改,并将它们摄取到hudi表中。它作为spark应用程序在两种模式下运行。

 在Spark使用需要在spark-submit中添加--packages org.apache.hudi:hudi-utilities-bundle_2.11:0.13.1,必填参数。从0.11.0版本开始,我们开始提供一个新的hudi-utilities-slim-bundle,旨在排除可能导致不同版本Spark冲突和兼容性问题的依赖关系。hudi-utilities-slim-bundle应该和对应Spark版本的Hudi Spark bundle一起使用,比如:在Spark中单独使用hudi-utilities-bundle会遇到兼容性问题,--packages org.apache.hudi:hudi-utilities-slim-bundle_2.12:0.13.1,org.apache.hudi:hudi-spark3.1-bundle_2.12:0.13.1。

Run Once Mode

在这种模式下,Deltastreamer执行一轮摄取,包括增量地从上游源提取事件并将它们摄取到hudi表中。 后台操作,如清理旧的文件版本和归档hoodie时间线,将自动作为运行的一部分执行。对于Merge-On-Read表,压缩也作为摄取的一部分内联运行,除非通过--disable-compaction禁用压缩。默认情况下,每次摄取时压缩都是内联运行的,这可以通过设置属性“hoodie.compact.inline.max.delta.commits”来改变。您既可以手动运行此spark应用程序,也可以使用任何cron触发器或工作流编排器(最常见的部署策略),如Apache Airflow来生成此应用程序。

下面是一个示例调用,在单运行模式下从kafka主题读取并写入yarn集群中的Merge On Read表类型。 

spark-submit --packages org.apache.hudi:hudi-utilities-bundle_2.11:0.13.1 \
 --master yarn \
 --deploy-mode cluster \
 --num-executors 10 \
 --executor-memory 3g \
 --driver-memory 6g \
 --conf spark.driver.extraJavaOptions="-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/varadarb_ds_driver.hprof" \
 --conf spark.executor.extraJavaOptions="-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/varadarb_ds_executor.hprof" \
 --queue hadoop-platform-queue \
 --conf spark.scheduler.mode=FAIR \
 --conf spark.yarn.executor.memoryOverhead=1072 \
 --conf spark.yarn.driver.memoryOverhead=2048 \
 --conf spark.task.cpus=1 \
 --conf spark.executor.cores=1 \
 --conf spark.task.maxFailures=10 \
 --conf spark.memory.fraction=0.4 \
 --conf spark.rdd.compress=true \
 --conf spark.kryoserializer.buffer.max=200m \
 --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
 --conf spark.memory.storageFraction=0.1 \
 --conf spark.shuffle.service.enabled=true \
 --conf spark.sql.hive.convertMetastoreParquet=false \
 --conf spark.ui.port=5555 \
 --conf spark.driver.maxResultSize=3g \
 --conf spark.executor.heartbeatInterval=120s \
 --conf spark.network.timeout=600s \
 --conf spark.eventLog.overwrite=true \
 --conf spark.eventLog.enabled=true \
 --conf spark.eventLog.dir=hdfs:///user/spark/applicationHistory \
 --conf spark.yarn.max.executor.failures=10 \
 --conf spark.sql.catalogImplementation=hive \
 --conf spark.sql.shuffle.partitions=100 \
 --driver-class-path $HADOOP_CONF_DIR \
 --class org.apache.hudi.utilities.deltastreamer.HoodieDeltaStreamer \
 --table-type MERGE_ON_READ \
 --source-class org.apache.hudi.utilities.sources.JsonKafkaSource \
 --source-ordering-field ts  \
 --target-base-path /user/hive/warehouse/stock_ticks_mor \
 --target-table stock_ticks_mor \
 --props /var/demo/config/kafka-source.properties \
 --schemaprovider-class org.apache.hudi.utilities.schema.FilebasedSchemaProvider

Continuous Mode

在这里,deltastreamer运行一个无限循环,每轮执行一次摄取循环,如Once Mode中所述。数据摄取的频率可以通过配置“--min-sync-interval-seconds”来控制。对于Merge-On-Read表,压缩以异步方式与摄取同时运行,除非通过传递“--disable-compaction”标志来禁用。每次摄取运行都会异步触发一个压缩请求,这个频率可以通过设置属性“hoodie.compact.inline.max.delta.commits”来改变。

由于摄取和压缩都在相同的spark context运行,您可以使用DeltaStreamer CLI中的资源分配配置,例如(“--delta-sync-scheduling-weight”、“--compact-scheduling-weight”、“--delta-sync-scheduling-minshare”和“--compact-scheduling-minshare”)来控制摄取和压缩之间的执行器分配。

下面是一个示例调用,以连续模式从kafka主题读取并写入yarn集群中的Merge On Read表类型。

spark-submit --packages org.apache.hudi:hudi-utilities-bundle_2.11:0.13.1 \
 --master yarn \
 --deploy-mode cluster \
 --num-executors 10 \
 --executor-memory 3g \
 --driver-memory 6g \
 --conf spark.driver.extraJavaOptions="-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/varadarb_ds_driver.hprof" \
 --conf spark.executor.extraJavaOptions="-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/varadarb_ds_executor.hprof" \
 --queue hadoop-platform-queue \
 --conf spark.scheduler.mode=FAIR \
 --conf spark.yarn.executor.memoryOverhead=1072 \
 --conf spark.yarn.driver.memoryOverhead=2048 \
 --conf spark.task.cpus=1 \
 --conf spark.executor.cores=1 \
 --conf spark.task.maxFailures=10 \
 --conf spark.memory.fraction=0.4 \
 --conf spark.rdd.compress=true \
 --conf spark.kryoserializer.buffer.max=200m \
 --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
 --conf spark.memory.storageFraction=0.1 \
 --conf spark.shuffle.service.enabled=true \
 --conf spark.sql.hive.convertMetastoreParquet=false \
 --conf spark.ui.port=5555 \
 --conf spark.driver.maxResultSize=3g \
 --conf spark.executor.heartbeatInterval=120s \
 --conf spark.network.timeout=600s \
 --conf spark.eventLog.overwrite=true \
 --conf spark.eventLog.enabled=true \
 --conf spark.eventLog.dir=hdfs:///user/spark/applicationHistory \
 --conf spark.yarn.max.executor.failures=10 \
 --conf spark.sql.catalogImplementation=hive \
 --conf spark.sql.shuffle.partitions=100 \
 --driver-class-path $HADOOP_CONF_DIR \
 --class org.apache.hudi.utilities.deltastreamer.HoodieDeltaStreamer \
 --table-type MERGE_ON_READ \
 --source-class org.apache.hudi.utilities.sources.JsonKafkaSource \
 --source-ordering-field ts  \
 --target-base-path /user/hive/warehouse/stock_ticks_mor \
 --target-table stock_ticks_mor \
 --props /var/demo/config/kafka-source.properties \
 --schemaprovider-class org.apache.hudi.utilities.schema.FilebasedSchemaProvider \
 --continuous

Spark Datasource写的任务

如写数据中所述,可以使用spark数据源将数据摄取到hudi表中。该机制允许您以Hudi格式摄取任何spark数据框架。Hudi Spark DataSource还支持Spark streaming,以将流源摄取到Hudi表中。对于Merge On Read表类型,默认情况下会打开内联压缩,在每次摄取后运行。压缩频率可以通过设置属性“hoodie.compact.inline.max.delta.commits”来改变。

下面是一个使用spark数据源的调用示例

inputDF.write()
       .format("org.apache.hudi")
       .options(clientOpts) // any of the Hudi client opts can be passed in as well
       .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY(), "_row_key")
       .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY(), "partition")
       .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY(), "timestamp")
       .option(HoodieWriteConfig.TABLE_NAME, tableName)
       .mode(SaveMode.Append)
       .save(basePath);