当前位置: 首页 > news >正文

Apache Hudi初探(八)(与spark的结合)--非bulk_insert模式

背景

之前讨论的都是’hoodie.datasource.write.operation’:'bulk_insert’的前提下,在这种模式下,是没有json文件的已形成如下的文件:

/dt=1/.hoodie_partition_metadata
/dt=1/2ffe3579-6ddb-4c5f-bf03-5c1b5dfce0a0-0_0-41263-0_20230528233336713.parquet
/dt=1/30b7d5b2-12e8-415a-8ec5-18206fe601c0-0_0-22102-0_20230528231643200.parquet
/dt=1/4abc1c6d-a8aa-4c15-affc-61a35171ce69-0_4-22106-0_20230528231643200.parquet
/dt=1/513dee80-2e8c-4db8-baee-a767b9dba41c-0_2-22104-0_20230528231643200.parquet
/dt=1/57076f86-0a62-4f52-8b50-31a5f769b26a-0_1-22103-0_20230528231643200.parquet
/dt=1/84553727-be9d-4273-bad9-0a38d9240815-0_0-59818-0_20230528233513387.parquet
/dt=1/fecd6a84-9a74-40b1-bfc1-13612a67a785-0_0-26640-0_20230528231723951.parquet

因为是"bulk insert"操作,所以没有去重的需要,所以直接采用spark原生的方式,
以下我们讨论非spark原生的方式,

闲说杂谈

继续Apache Hudi初探(二)(与spark的结合)
剩下的代码:

 val reconcileSchema = parameters(DataSourceWriteOptions.RECONCILE_SCHEMA.key()).toBooleanval (writeResult, writeClient: SparkRDDWriteClient[HoodieRecordPayload[Nothing]]) =...case _ => { // any other operation// register classes & schemasval (structName, nameSpace) = AvroConversionUtils.getAvroRecordNameAndNamespace(tblName)sparkContext.getConf.registerKryoClasses(Array(classOf[org.apache.avro.generic.GenericData],classOf[org.apache.avro.Schema]))// TODO(HUDI-4472) revisit and simplify schema handlingval sourceSchema = AvroConversionUtils.convertStructTypeToAvroSchema(df.schema, structName, nameSpace)val latestTableSchema = getLatestTableSchema(sqlContext.sparkSession, tableMetaClient).getOrElse(sourceSchema)val schemaEvolutionEnabled = parameters.getOrDefault(DataSourceReadOptions.SCHEMA_EVOLUTION_ENABLED.key(), "false").toBooleanvar internalSchemaOpt = getLatestTableInternalSchema(hoodieConfig, tableMetaClient)val writerSchema: Schema =if (reconcileSchema) {// In case we need to reconcile the schema and schema evolution is enabled,// we will force-apply schema evolution to the writer's schemaif (schemaEvolutionEnabled && internalSchemaOpt.isEmpty) {internalSchemaOpt = Some(AvroInternalSchemaConverter.convert(sourceSchema))}if (internalSchemaOpt.isDefined) {...// Convert to RDD[HoodieRecord]val genericRecords: RDD[GenericRecord] = HoodieSparkUtils.createRdd(df, structName, nameSpace, reconcileSchema,org.apache.hudi.common.util.Option.of(writerSchema))val shouldCombine = parameters(INSERT_DROP_DUPS.key()).toBoolean ||operation.equals(WriteOperationType.UPSERT) ||parameters.getOrElse(HoodieWriteConfig.COMBINE_BEFORE_INSERT.key(),HoodieWriteConfig.COMBINE_BEFORE_INSERT.defaultValue()).toBooleanval hoodieAllIncomingRecords = genericRecords.map(gr => {val processedRecord = getProcessedRecord(partitionColumns, gr, dropPartitionColumns)val hoodieRecord = if (shouldCombine) {val orderingVal = HoodieAvroUtils.getNestedFieldVal(gr, hoodieConfig.getString(PRECOMBINE_FIELD), false, parameters.getOrElse(DataSourceWriteOptions.KEYGENERATOR_CONSISTENT_LOGICAL_TIMESTAMP_ENABLED.key(),DataSourceWriteOptions.KEYGENERATOR_CONSISTENT_LOGICAL_TIMESTAMP_ENABLED.defaultValue()).toBoolean).asInstanceOf[Comparable[_]]DataSourceUtils.createHoodieRecord(processedRecord,orderingVal,keyGenerator.getKey(gr),hoodieConfig.getString(PAYLOAD_CLASS_NAME))} else {DataSourceUtils.createHoodieRecord(processedRecord, keyGenerator.getKey(gr), hoodieConfig.getString(PAYLOAD_CLASS_NAME))}hoodieRecord}).toJavaRDD()val writerDataSchema = if (dropPartitionColumns) generateSchemaWithoutPartitionColumns(partitionColumns, writerSchema) else writerSchema// Create a HoodieWriteClient & issue the write.val client = hoodieWriteClient.getOrElse(DataSourceUtils.createHoodieClient(jsc, writerDataSchema.toString, path,tblName, mapAsJavaMap(addSchemaEvolutionParameters(parameters, internalSchemaOpt) - HoodieWriteConfig.AUTO_COMMIT_ENABLE.key))).asInstanceOf[SparkRDDWriteClient[HoodieRecordPayload[Nothing]]]if (isAsyncCompactionEnabled(client, tableConfig, parameters, jsc.hadoopConfiguration())) {asyncCompactionTriggerFn.get.apply(client)}if (isAsyncClusteringEnabled(client, parameters)) {asyncClusteringTriggerFn.get.apply(client)}val hoodieRecords =if (hoodieConfig.getBoolean(INSERT_DROP_DUPS)) {DataSourceUtils.dropDuplicates(jsc, hoodieAllIncomingRecords, mapAsJavaMap(parameters))} else {hoodieAllIncomingRecords}client.startCommitWithTime(instantTime, commitActionType)val writeResult = DataSourceUtils.doWriteOperation(client, hoodieRecords, instantTime, operation)(writeResult, client)}
  • 如果开启了Schema Evolution,也就是hoodie.datasource.write.reconcile.schematrue,默认是false,就会进行schema的合并
    convertStructTypeToAvroSchema 把df的schema转换成avro的schema
    并且从*.hoodie/20230530073115535.deltacommit* 获取internalSchemaOpt,具体的合并就是把即将写入的schema和internalSchemaOpt进行合并
    最后赋值给writerSchema,有可能还需要hoodie.schema.on.read.enable,默认是false

  • HoodieSparkUtils.createRdd 创建RDD
    把df转换为了RDD[GenericRecord]类型,赋值给genericRecords

  • val hoodieAllIncomingRecords = genericRecords.map(gr => {

    • 首先如果是hoodie.datasource.write.drop.partition.columnstrue(默认是false),则会从schema中删除hoodie.datasource.write.
      partitionpath.field
      字段
    • 如果hoodie.datasource.write.insert.drop.duplicatestrue(默认是false)或者hoodie.datasource.write.operationupsert(默认
      upsert),或者hoodie.combine.before.inserttrue(默认是false),
      则会创建HoodieAvroRecord<>(hKey, payload)类型的实例,其中HoodieKeyrecordkey和partitionpath组成,playloadOverwriteWithLatestAvroPayload实例
    • hoodieAllIncomingRecords就变成了RDD[HoodieAvroRecord]
  • writerDataSchema= client 这些就是创建SparkRDDWriteClient 客户端

  • isAsyncCompactionEnabled
    默认asyncCompactionTriggerFnDefined是没有的,所以不会开启异步的CompactionisAsyncClusteringEnabled同理也是

  • val hoodieRecords =
    如果配置了hoodie.datasource.write.insert.drop.duplicatestrue(默认是false),则会进行去重处理,具体是调用DataSourceUtils.dropDuplicates方法:

    SparkRDDReadClient client = new SparkRDDReadClient<>(new HoodieSparkEngineContext(jssc), writeConfig);return client.tagLocation(incomingHoodieRecords).filter(r -> !((HoodieRecord<HoodieRecordPayload>) r).isCurrentLocationKnown());
    
    • SparkRDDReadClient client 在创建Client的时候,会进行索引的创建this.index = SparkHoodieIndexFactory.createIndex(clientConfig);
      如果有hoodie.index.class设置,则实例化对象,否则根据hoodie.index.type的值来建立索引(默认是HoodieSimpleIndex,适合做测试用)
    • client.tagLocation(incomingHoodieRecords)…
      从要插入的记录中过滤出在index中不存在的记录,最终调用的是index.tagLocation方法
      如果hoodie.datasource.write.insert.drop.duplicatesfalse,则保留所有的记录
  • client.startCommitWithTime 开始写操作,这涉及到回滚的操作

    • 会先过滤出需要回滚的的的写失败的文件,如果hoodie.cleaner.policy.failed.writesEAGER(默认是EAGER),就会在这次提交中回滚失败的文件
    • 然后创建一个后缀为deltacommit.requested的文件,此时没有真正的写
  • val writeResult = DataSourceUtils.doWriteOperation
    真正的写操作

相关文章:

Apache Hudi初探(八)(与spark的结合)--非bulk_insert模式

背景 之前讨论的都是’hoodie.datasource.write.operation’:bulk_insert’的前提下&#xff0c;在这种模式下&#xff0c;是没有json文件的已形成如下的文件&#xff1a; /dt1/.hoodie_partition_metadata /dt1/2ffe3579-6ddb-4c5f-bf03-5c1b5dfce0a0-0_0-41263-0_202305282…...

Java之旅(九)

Java 循环语句 Java 中的循环语句包括 for、while 和 do-while&#xff0c;它们都可以用于实现循环结构。 for 语句用于循环执行一段代码块&#xff0c;直到给定的条件表达式的布尔值为 false。 for 语句的一般格式如下&#xff1a; for (initialization; condition; update…...

6年测试经验之谈,为什么要做自动化测试?

一、自动化测试 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。 个人认为&#xff0c;只要能服务于测试工作&#xff0c;能够帮助我们提升工作效率的&#xff0c;不管是所谓的自动化工具&#xff0c;还是简单的SQL 脚本、批处理脚本&#xff0c;还是自己编写…...

二分法的边界条件 2517. 礼盒的最大甜蜜度

2517. 礼盒的最大甜蜜度 给你一个正整数数组 price &#xff0c;其中 price[i] 表示第 i 类糖果的价格&#xff0c;另给你一个正整数 k 。 商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。 返回礼盒的 最大 甜蜜度。 记录一…...

java设计模式(十六)命令模式

目录 定义模式结构角色职责代码实现适用场景优缺点 定义 命令模式&#xff08;Command Pattern&#xff09; 又叫动作模式或事务模式。指的是将一个请求封装成一个对象&#xff0c;使发出请求的责任和执行请求的责任分割开&#xff0c;然后可以使用不同的请求把客户端参数化&a…...

[运维] iptables限制指定ip访问指定端口和只允许指定ip访问指定端口

iptables限制指定ip访问指定端口 要使用iptables限制特定IP地址访问特定端口&#xff0c;您可以使用以下命令&#xff1a; iptables -A INPUT -p tcp -s <IP地址> --dport <端口号> -j DROP请将 <IP地址> 替换为要限制的IP地址&#xff0c;将 <端口号&g…...

JS学习笔记(3. 流程控制)

1. 分歧 1.1 if条件 if (条件) {...} // 为真则执行&#xff0c;单条语句可省略大括号 if (条件) {...} else {...}// 为真则执行if&#xff0c;否则执行else if (条件1) {...} else if (条件2) {...} else {...} // 条件1为真则&#xff0c;条件2为真则&#xff0c;否则执…...

遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型教程

详情点击链接&#xff1a;遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型教程 一&#xff1a;平台及基础开发平台 GEE平台及典型应用案例&#xff1b; GEE开发环境及常用数据资源&#xff1b; ChatGPT、文心一言等GPT模型 JavaScript基础&#xff1b; GEE遥感云重…...

什么是文件描述符以及重定向的本质和软硬链接(Linux)

目录 1 什么是文件&#xff1f;什么是文件操作&#xff1f;认识系统接口open 什么是文件描述符认识Linux底层进程如何打开的文件映射关系重定向的本质理解软硬链接扩展问题 1 什么是文件&#xff1f;什么是文件操作&#xff1f; 文件 文件内容 文件属性&#xff08;文件属性…...

LVM逻辑卷元数据丢失恢复案例 —— 筑梦之路

Lvm常见的故障主要是pv出现异常&#xff0c;有以下几种情况 一个是pv所在的磁盘发生了lvm的元数据损坏一个是系统无法识别到pv所在的磁盘一个是系统异常&#xff0c;断电等导致重启后盘符发生变化&#xff0c;也就是系统识别的磁盘uuid发生变化&#xff0c;但是wwid还是可以对应…...

Java技术规范概览

Java技术规范 目录概述需求&#xff1a; 设计思路实现思路分析1.Java JSR的部分2.JSR-000373.JSR-0000394.JSR-000337 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a bet…...

【OpenMMLab AI实战营第二期】二十分钟入门OpenMMLab笔记

OpenMMlab 主页&#xff1a;openmmlab.com 开源地址&#xff1a;https://github.com/open-mmlab 学习视频地址&#xff1a;https://www.bilibili.com/video/BV1js4y1i72P/ 概述 开源成为人工智能行业发展引擎 时间轴 theano&#xff1a;2007 Caffe&#xff1a;2013 Ten…...

docker-compose单机容器集群编排

docker-compose dockerfile模板文件可以定义一个独立的应用容器&#xff0c;如果需要多个容器就需要服务编排。服务编排有很多技术方案 docker-compose开源的项目实现对容器集群的快速编排 docker-compose将所管理的容器分为三层&#xff0c;分别为工程&#xff0c;服务&#…...

CentOS7 安装Gitlab

1、安装依赖 sudo yum install -y curl openssh-server ca-certificates tzdata perl libsemanage-devel 2、安装邮件服务工具 sudo yum install -y postfix 3、配置GitLab 软件源镜像 curl -fsSL https://packages.gitlab.cn/repository/raw/scripts/setup.sh | /bin/bash …...

Mysql InnoDB的Buffer Pool

Buffer Pool 在MySQL服务器启动的时候就向操作系统申请了⼀⽚连续的内存&#xff0c;他们给这⽚内存起了个名&#xff0c;叫做Buffer Pool&#xff08;中⽂名 是缓冲池&#xff09;。 默认情况下Buffer Pool只有128M⼤⼩&#xff0c;最⼩值为5M&#xff0c;通过修改配置文件设…...

SMTP简单邮件传输协议(C/C++ 发送电子邮件)

SMTP是用于通过Internet发送电子邮件的协议。电子邮件客户端&#xff08;如Microsoft Outlook或macOS Mail应用程序&#xff09;使用SMTP连接到邮件服务器并发送电子邮件。邮件服务器还使用SMTP将邮件从一个邮件服务器交换到另一个。它不用于从服务器下载电子邮件&#xff1b;相…...

uploads靶场通关(1-11关)

Pass-01&#xff08;JS校验&#xff09; 看题目我们准备好我们的php脚本文件&#xff0c;命名为1.php 上传该php文件&#xff0c;发现上传失败 方法一&#xff1a;将浏览器的JavaScript禁用 然后就能上传了 方法二&#xff1a; 查看源码&#xff0c;发现只能上传以下形式的文…...

6.1黄金探底回升是否到顶,今日多空如何布局

近期有哪些消息面影响黄金走势&#xff1f;今日黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周三(5月31日)黄金期货价格攀升&#xff0c;美国国债收益率下降推动金价升至一周最高收盘位。美市尾盘&#xff0c;现货黄金收报1962.42美元/盎司&#xff0c;上升3…...

自定义ViewGroup实现流式布局

目录 1、View的绘制流程 2、自定义ViewGroup构造函数的作用 3、onMeasure 方法 3.1、View的度量方式 3.2、onMeasure方法参数的介绍 3.3、自定义ViewGroup onMeasure 方法的实现 4、onLayout方法 5、onDraw方法 6、自定义View的生命周期 7、自定义流式布局的实现 扩展&#xff…...

Git版本控制

目录 版本控制 概念 为什么需要版本控制&#xff1f; 常见的版本控制工具 Git 1、安装 2、了解基本的Linux命令 3、配置git 用户名和邮箱 4、git 工作模式 5、git 项目管理 6、git 分支 托管平台 远程仓库 Gitee 关联多个远程库 Git服务器 Git GUI 版本控制 概…...

若依之权限处理

若依之权限处理 若依前后端不分离版本使用的是shiro进行权限控制&#xff0c;本文主要是对shiro在若依中的使用进行分析。 RBAC权限模型 RBAC是指基于角色的访问控制。其基本思想是&#xff0c;对系统的各种权限不是直接授予具体的用户&#xff0c;而是在用户集合与权限集合…...

华为OD机试真题 Java 实现【矩阵最大值】【2023 B卷 100分】,附详细解题思路

一、题目描述 给定一个仅包含0和1的N*N的二维矩阵,请计算二维矩阵的最大值。 计算规则如下: 1、每行元素按下标顺序组成一个二进制数(下标越大越排在低位),二进制数的值就是该行的值。矩阵各行值之和为矩阵的值。 2、允许通过向左或向右整体循环移动每行元素来改变各元…...

ModuleNotFoundError: No module named ‘transformers_modules.chatglm-6b_v1‘的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

MMPretrain代码课

安装注意事项 训练时需要基于算法库源码进行开发&#xff0c;所以需要git clone mmpretrain仓库。如果只调用&#xff0c;则pip install 即可。 from mmpretrain import get_model, list_models,inference_model分别用于模型的获取、例举、推理 此时还没加载预训练权重 tor…...

Selenium自动化程序被检测为爬虫,怎么屏蔽和绕过

Selenium 操作被屏蔽 使用selenium自动化网页时&#xff0c;有一定的概率会被目标网站识别&#xff0c;一旦被检测到&#xff0c;目标网站会拦截该客户端做出的网页操作。 比如淘宝和大众点评的登录页&#xff0c;当手工打开浏览器&#xff0c;输入用户名和密码时&#xff0c…...

Nvidia Jetson Orin:开发技巧

Jetson PXXX定义 P2180 -> Jetson TX1 P3310 -> Jetson TX2 P3489 -> Jetson TX2i P3448 -> Jetson Nano devkit P3448-0020 -> Jetson Nano production module P2888 -> Jetson Xavier P2888-0060 -> Jetson Xavier-8GB P3701 -> Jetson AGX Orin D…...

为什么需要 git 和 相关的小知识

为什么需要git和相关的小知识 先看一个实际需求&#xff0c;引出Git 问题: 公司五一活动计划 ● 先说一个最简单的情况&#xff0c;比如你做了公司五一活动计划书(如图) 解决方案: 版本管理工具(Git) 一句话: Git 是目前最流行的分布式版本控制软件 Git 是怎么来的? Git…...

(详解)vue中实现主题切换的三种方式

目录 一、背景 二、实现思路 方法1&#xff1a;定义全局的CSS变量 方法2&#xff1a;切换已定义好的css文件 方法3&#xff1a;切换顶级CSS类名 (需使用css处理器,如sass、less等) 一、背景 在我们开发中我们会遇到像是需要切换程序风格、主题切换啦这种应用场景。 参考大佬…...

英国皇家植物园采用机器学习预测植物抗疟性,将准确率从 0.46 提升至 0.67

内容一览&#xff1a;疟疾是严重危害人类生命健康的重大传染病&#xff0c;研究人员一直在致力于寻找新的植物源性抗疟疾化合物&#xff0c;以研发相关药物。近期英国皇家植物园利用机器学习 算法 有效预测了植物抗疟性&#xff0c;该研究成果目前已发表在《Frontiers in Plant…...

基于Locust实现MQTT协议服务的压测脚本

一、背景简介 业务背景大概介绍一下&#xff0c;就是按照国标规定&#xff0c;车辆需要上传一些指定的数据到ZF的指定平台&#xff0c;同时车辆也会把数据传到企业云端服务上&#xff0c;于是乎就产生了一些性能需求。 目前我们只是先简单的进行了一个性能场景的测试&#xf…...