测试hudi-0.7.0对接spark structure streaming

测试hudi-0.7.0对接spark structure streaming

测试环境

Hudi version :0.7.0
Spark version :2.4.0
Hive version :2.1.1
Hadoop version :3.0.0
Storage (HDFS/S3/GCS..) :HDFS
Running on Docker? (yes/no) :no

测试内容

表类型:copy on write
插入方式:bulkinsert
控制文件大小:clustering配置
是否同步hive:同步hive

测试的参数配置如下:

    	//hudi配置
    	.option(TABLE_TYPE_OPT_KEY, "COPY_ON_WRITE")
    	.option("hoodie.datasource.write.operation","bulk_insert")
		.option(PRECOMBINE_FIELD_OPT_KEY, "kafka_timestamp")// 以kafka分区和偏移量作为组合主键
        .option(RECORDKEY_FIELD_OPT_KEY, "kafka_partition_offset")// 以当前日期作为分区
        .option(PARTITIONPATH_FIELD_OPT_KEY, "partition_date")
        
        //clustering配置
        .option("hoodie.parquet.small.file.limit", "0")
     	.option("hoodie.clustering.inline", "true")
    	.option("hoodie.clustering.inline.max.commits", "4")
    	.option("hoodie.clustering.plan.strategy.target.file.max.bytes", "1073741824")
    	.option("hoodie.clustering.plan.strategy.small.file.limit", "629145600")
    	.option("hoodie.clustering.plan.strategy.sort.columns", "") //optional, if sorting is needed as part of rewriting data
		
		//hive配置
		.option("hoodie.table.name", "copy_on_write_table")
		.option("hoodie.datasource.write.hive_style_partitioning", "true")
		.option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY, "hudi")
  		.option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY, "hudi_hive_sync")
  		.option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY, "true")
        .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"")
        .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY, "jdbc:hive2://ip:port")
  		.option(DataSourceWriteOptions.HIVE_USER_OPT_KEY, "USERNAME")
  		.option(DataSourceWriteOptions.HIVE_PASS_OPT_KEY, "PASSWORD")
  		.option("HoodieWriteConfig.EMBEDDED_TIMELINE_SERVER_ENABLED", "false")

		//清理配置
		.option("hoodie.cleaner.policy","KEEP_LATEST_FILE_VERSIONS")
		.option("hoodie.cleaner.fileversions.retained","1")
		.option("hoodie.cleaner.automatic","true")
		.option("hoodie.clean.async","true")

测试代码如下:

object SparkHudi {
  val logger = Logger.getLogger(SparkHudi.getClass)

  def main(args: Array[String]): Unit = {

    val spark = SparkSession
      .builder
      .appName("SparkHudi")
      //.master("local[*]")
      .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
      .config("spark.default.parallelism", 9)
      .config("spark.sql.shuffle.partitions", 9)
      .enableHiveSupport()
      .getOrCreate()

    // 添加监听器,每一批次处理完成,将该批次的相关信息,如起始offset,抓取记录数量,处理时间打印到控制台
	spark.streams.addListener(new StreamingQueryListener() {
    	override def onQueryStarted(queryStarted: QueryStartedEvent): Unit = {
        	println("Query started: " + queryStarted.id)
    	}
    	override def onQueryTerminated(queryTerminated: QueryTerminatedEvent): Unit = {
       		println("Query terminated: " + queryTerminated.id)
    	}
    	override def onQueryProgress(queryProgress: QueryProgressEvent): Unit = {
        	println("Query made progress: " + queryProgress.progress)
    	}
	})

    // 定义kafka流
    val dataStreamReader = spark
      .readStream
      .format("kafka")
      .option("kafka.bootstrap.servers", "kafka IP:9092")
      .option("subscribe", "TopicName")
      .option("startingOffsets", "latest")
      .option("maxOffsetsPerTrigger", 100000)

    // 加载流数据,这里因为只是测试使用,直接读取kafka消息而不做其他处理,是spark结构化流会自动生成每一套消息对应的kafka元数据,如消息所在主题,分区,消息对应offset等。
    val df = dataStreamReader.load()
      .selectExpr(
        "topic as kafka_topic"
        "CAST(partition AS STRING) kafka_partition",
        "cast(timestamp as String) kafka_timestamp",
        "CAST(offset AS STRING) kafka_offset",
        "CAST(key AS STRING) kafka_key",
        "CAST(value AS STRING) kafka_value",
        "current_timestamp() current_time",
)
       .selectExpr(
        "kafka_topic"
 		"concat(kafka_partition,'-',kafka_offset) kafka_partition_offset",
        "kafka_offset",
        "kafka_timestamp",
        "kafka_key",
        "kafka_value",
    	"substr(current_time,1,10) partition_date")

	// 创建并启动query
    val query = df
      .writeStream
      .queryName("demo").
      .foreachBatch { (batchDF: DataFrame, _: Long) => {
        batchDF.persist()
        println(LocalDateTime.now() + "start writing cow table")
        
		batchDF.write.format("org.apache.hudi")
        	.option(TABLE_TYPE_OPT_KEY, "COPY_ON_WRITE")
        	.option("hoodie.datasource.write.operation","bulk_insert")
			.option(PRECOMBINE_FIELD_OPT_KEY, "kafka_timestamp")// 以kafka分区和偏移量作为组合主键
            .option(RECORDKEY_FIELD_OPT_KEY, "kafka_partition_offset")// 以当前日期作为分区
            .option(PARTITIONPATH_FIELD_OPT_KEY, "partition_date")
            
            //clustering配置
            .option("hoodie.parquet.small.file.limit", "0")
         	.option("hoodie.clustering.inline", "true")
        	.option("hoodie.clustering.inline.max.commits", "4")
        	.option("hoodie.clustering.plan.strategy.target.file.max.bytes", "1073741824")
        	.option("hoodie.clustering.plan.strategy.small.file.limit", "629145600")
        	.option("hoodie.clustering.plan.strategy.sort.columns", "") //optional, if sorting is needed as part of rewriting data
			
			//hive配置
			.option("hoodie.table.name", "copy_on_write_table")
			.option("hoodie.datasource.write.hive_style_partitioning", "true")
			.option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY, "hudi")
      		.option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY, "hudi_hive_sync")
      		.option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY, "true")
            .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"")
            .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY, "jdbc:hive2://ip:port")
      		.option(DataSourceWriteOptions.HIVE_USER_OPT_KEY, "USERNAME")
      		.option(DataSourceWriteOptions.HIVE_PASS_OPT_KEY, "PASSWORD")
      		.option("HoodieWriteConfig.EMBEDDED_TIMELINE_SERVER_ENABLED", "false")

			//清理配置
			.option("hoodie.cleaner.policy","KEEP_LATEST_FILE_VERSIONS")
			.option("hoodie.cleaner.fileversions.retained","1")
			.option("hoodie.cleaner.automatic","true")
			.option("hoodie.clean.async","true")
            .mode(SaveMode.Append)
            .save("/hudi/sparkHudi/hudi表")
            
        println(LocalDateTime.now() + "finish")
        batchDF.unpersist()
      }
      }
      .option("checkpointLocation", "/tmp/sparkHudi/checkpoint/")
      .start()

    query.awaitTermination()
  }
}

测试结果

将之前的旧版本hudi-0.6.0替换成hudi-0.7.0,经测试没有报错,符合预期。新版本增加了clustering配置,小文件会合并成大文件,减少了查询引擎需要扫描的文件数,因而提高了查询效率。不过合并过程会降低写入速度。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
随着互联网的发展,数据的不断膨胀,从刚开始的关系型数据库到非关系型数据库,再到大数据技术,技术的不断演进最终是随着数据膨胀而不断改变,最初的数据仓库能解决我们的问题,但是随着时代发展,企业已经不满足于数据仓库,希望有更强大的技术来支撑数据的存储,包括结构化,非结构化的数据等,希望能够积累企业的数据,从中挖掘出更大的价值。基于这个背景,数据湖的技术应运而生。本课程基于真实的企业数据湖案例进行讲解,结合业务实现数据湖平台,让大家在实践中理解和掌握数据湖技术,未来数据湖的需求也会不断加大,希望同学们抓住这个机遇。项目中将以热门的互联网电商业务场景为案例讲解,具体分析指标包含:流量分析,订单分析,用户行为分析,营销分析,广告分析等,能承载海量数据的实时分析,数据分析涵盖全端(PC、移动、小程序)应用。Apache Hudi代表Hadoop Upserts anD Incrementals,管理大型分析数据集在HDFS上的存储。Hudi的主要目的是高效减少摄取过程中的数据延迟。Hudi的出现解决了现有hadoop体系的几个问题:1、HDFS的可伸缩性限制 2、需要在Hadoop中更快地呈现数据 3、没有直接支持对现有数据的更新和删除 4、快速的ETL和建模 5、要检索所有更新的记录,无论这些更新是添加到最近日期分区的新记录还是对旧数据的更新,Hudi都允许用户使用最后一个检查点时间戳,此过程不用执行扫描整个源表的查询。 本课程包含的技术: 开发工具为:IDEA、WebStorm Flink1.9.0、HudiClickHouseHadoop2.7.5 Hbase2.2.6Kafka2.1.0 Hive2.2.0HDFS、MapReduceSpark、ZookeeperBinlog、Canal、MySQLSpringBoot2.0.2.RELEASE SpringCloud Finchley.RELEASEVue.js、Nodejs、HighchartsLinux Shell编程课程亮点: 1.与企业接轨、真实工业界产品 2.ClickHouse高性能列式存储数据库 3.大数据热门技术Flink4.Flink join 实战 5.Hudi数据湖技术6.集成指标明细查询 7.主流微服务后端系统 8.数据库实时同步解决方案 9.涵盖主流前端技术VUE+jQuery+Ajax+NodeJS 10.集成SpringCloud实现统一整合方案 11.互联网大数据企业热门技术栈 12.支持海量数据的实时分析 13.支持全端实时数据分析 14.全程代码实操,提供全部代码和资料 15.提供答疑和提供企业技术方案咨询企业一线架构师讲授,代码在老师的指导下企业可以复用,提供企业解决方案。  版权归作者所有,盗版将进行法律维权。  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据湖填坑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值