【数据湖Hudi-5-Hudi集成Spark-并发控制处理】

并发控制

1.Hudi支持的并发控制

1.MVCC

Hudi的表操作,如压缩、清理、提交,hudi会利用多版本并发控制来提供多个表操作写入和查询之间的快照隔离。使用MVCC这种模型,Hudi支持并发任意数量的操作作业,并保证不会发生任何冲突。Hudi默认这种模型。MVCC方式所有的table service都使用同一个writer来保证没有冲突,避免竟态条件。

2.OPTIMISTIC CONCURRENCY

针对写入操作(upsert、insert等)利用乐观锁并发控制来启用多个writer将数据写到同一个表中,Hudi支持文件级的乐观一致性,即对于发生在同一个表中的任何2个提交(写入),如果它们没有写入正在更改的重叠文件,则允许两个写入都成功。此功能处于实验阶段,需要用到Zookeeper或HiveMetastore来获取锁.

  • Hudi默认使用MVCC模式进行并发控股写入数据,但是如果要修改为OPTIMISTIC CONCURRENCY的话,需要进行下面的配置:
    1)参数
    (1)如果需要开启乐观并发写入,需要设置以下属性
    hoodie.write.concurrency.mode=optimistic_concurrency_control
    hoodie.cleaner.policy.failed.writes=LAZY
    hoodie.write.lock.provider=
    Hudi获取锁的服务提供两种模式使用zookeeper、HiveMetaStore(选一种即可)
    (2)相关zookeeper参数
    hoodie.write.lock.provider=org.apache.hudi.client.transaction.lock.ZookeeperBasedLockProvider
    hoodie.write.lock.zookeeper.url
    hoodie.write.lock.zookeeper.port
    hoodie.write.lock.zookeeper.lock_key
    hoodie.write.lock.zookeeper.base_path
    (3)相关HiveMetastore参数,HiveMetastore URI是从运行时加载的hadoop配置文件中提取的
    hoodie.write.lock.provider=org.apache.hudi.hive.HiveMetastoreBasedLockProvider
    hoodie.write.lock.hivemetastore.database
    hoodie.write.lock.hivemetastore.table

3.并发写入方式修改以及参数设置

  • 1.使用Spark DataFrame并发写入
    (1)启动spark-shell
spark-shell \
  --conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
  --conf 'spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog' \
  --conf 'spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension'

(2)编写代码

import org.apache.hudi.QuickstartUtils._
import scala.collection.JavaConversions._
import org.apache.spark.sql.SaveMode._
import org.apache.hudi.DataSourceReadOptions._
import org.apache.hudi.DataSourceWriteOptions._
import org.apache.hudi.config.HoodieWriteConfig._

val tableName = "hudi_trips_cow"
val basePath = "file:///tmp/hudi_trips_cow"
val dataGen = new DataGenerator

val inserts = convertToStringList(dataGen.generateInserts(10))
val df = spark.read.json(spark.sparkContext.parallelize(inserts, 2))
df.write.format("hudi").
  options(getQuickstartWriteConfigs).
  option(PRECOMBINE_FIELD_OPT_KEY, "ts").
  option(RECORDKEY_FIELD_OPT_KEY, "uuid").
  option(PARTITIONPATH_FIELD_OPT_KEY, "partitionpath").
  option("hoodie.write.concurrency.mode", "optimistic_concurrency_control").
  option("hoodie.cleaner.policy.failed.writes", "LAZY").
  option("hoodie.write.lock.provider", "org.apache.hudi.client.transaction.lock.ZookeeperBasedLockProvider").
  option("hoodie.write.lock.zookeeper.url", "hadoop1,hadoop2,hadoop3").
  option("hoodie.write.lock.zookeeper.port", "2181").
  option("hoodie.write.lock.zookeeper.lock_key", "test_table").
  option("hoodie.write.lock.zookeeper.base_path", "/multiwriter_test").
  option(TABLE_NAME, tableName).
  mode(Append).
  save(basePath)

(3)使用zk客户端,验证是否使用了zk。

zkCli.sh 
[zk: localhost:2181(CONNECTED) 0] ls /

(4)zk下产生了对应的目录,/multiwriter_test下的目录,为代码里指定的lock_key

[zk: localhost:2181(CONNECTED) 1] ls /multiwriter_test
  • 2.运行Delta Streamer
spark-submit \
--class org.apache.hudi.utilities.deltastreamer.HoodieDeltaStreamer  \
/opt/module/spark-3.2.2/jars/hudi-utilities-bundle_2.12-0.12.0.jar \
--props hdfs://hadoop1:8020/hudi-props/kafka-multiwriter-source.propertis \
--schemaprovider-class org.apache.hudi.utilities.schema.FilebasedSchemaProvider  \
--source-class org.apache.hudi.utilities.sources.JsonKafkaSource  \
--source-ordering-field userid \
--target-base-path hdfs://hadoop1:8020/tmp/hudi/hudi_test_multi  \
--target-table hudi_test_multi \
--op INSERT \
--table-type MERGE_ON_READ

3)查看zk是否产生新的目录

zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[zk: localhost:2181(CONNECTED) 1] ls /multiwriter_test2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用hudi-spark-client写数据到hudi表的步骤如下: 1. 首先,创建一个SparkSession对象,并配置相关的SparkHudi属性。例如: ```scala val spark = SparkSession.builder() .appName("HudiSparkClientExample") .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .config("spark.sql.hive.convertMetastoreParquet", "false") .config("spark.sql.sources.partitionColumnTypeInference.enabled", "false") .config("spark.sql.hive.verifyPartitionPath", "false") .config("spark.hadoop.hive.exec.dynamic.partition.mode", "nonstrict") .config("spark.hadoop.hive.exec.dynamic.partition", "true") .config("spark.sql.warehouse.dir", "hdfs://localhost:9000/user/hive/warehouse") .config("spark.sql.catalogImplementation", "hive") .enableHiveSupport() .getOrCreate() ``` 2. 创建一个DataFrame对象,用于存储要写入Hudi表的数据。 ```scala val data = Seq( (1, "John Doe", 25), (2, "Jane Smith", 30) ) val df = spark.createDataFrame(data).toDF("id", "name", "age") ``` 3. 使用`HoodieSparkSqlWriter`将DataFrame写入Hudi表。指定要写入的表名、要使用的主键列以及要使用的分区列。 ```scala df.write .format("org.apache.hudi") .option("hoodie.table.name", "my_hudi_table") .option("hoodie.datasource.write.precombine.field", "id") .option("hoodie.datasource.write.recordkey.field", "id") .option("hoodie.datasource.write.partitionpath.field", "age") .mode(SaveMode.Append) .save("hdfs://localhost:9000/path/to/hudi_table") ``` 4. 最后,关闭SparkSession对象。 ```scala spark.stop() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值