Hudi(3):Hudi之基本概念

news2025/1/11 19:55:48

目录

0. 相关文章链接

1. 时间轴(TimeLine)

1.1. Instant action:在表上执行的操作类型

1.2. Instant time

1.3. State

1.4. 两个时间概念

2. 文件布局(File Layout)

2.1. Hudi表的文件结构

2.2. Hudi存储的两个部分

2.3. Hudi的具体文件说明

3. 索引(Index)

3.1. 原理

3.2. 索引选项

3.3. 全局索引与非全局索引

3.4. 索引的选择策略

3.4.1. 对事实表的延迟更新

3.4.2. 对事件表的去重

3.4.3. 对维度表的随机更删

4. 表类型(Table Types)

4.1. Copy On Write

4.2. Merge On Read

4.3. COW与MOR的对比

5. 查询类型(Query Types)

5.1. Snapshot Queries

5.2. Incremental Queries

5.3. Read Optimized Queries

5.4. 不同表支持的查询类型

6. Compaction


0. 相关文章链接

 Hudi文章汇总 

1. 时间轴(TimeLine)

        Hudi的核心是维护表上在不同的即时时间(instants)执行的所有操作的时间轴(timeline),这有助于提供表的即时视图,同时还有效地支持按到达顺序检索数据。一个instant由以下三个部分组成:

1.1. Instant action:在表上执行的操作类型

  • COMMITS:一次commit表示将一批数据原子性地写入一个表。
  • CLEANS:清除表中不再需要的旧版本文件的后台活动。
  • DELTA_COMMIT:增量提交指的是将一批数据原子性地写入一个MergeOnRead类型的表,其中部分或所有数据可以写入增量日志。
  • COMPACTION:合并Hudi内部差异数据结构的后台活动,例如:将更新操作从基于行的log日志文件合并到列式存储的数据文件。在内部,COMPACTION体现为timeline上的特殊提交。
  • ROLLBACK:表示当commit/delta_commit不成功时进行回滚,其会删除在写入过程中产生的部分文件。
  • SAVEPOINT:将某些文件组标记为已保存,以便其不会被删除。在发生灾难需要恢复数据的情况下,它有助于将数据集还原到时间轴上的某个点。

1.2. Instant time

  • 通常是一个时间戳(例如:20190117010349),它按照动作开始时间的顺序单调增加。

1.3. State

  • REQUESTED:表示某个action已经调度,但尚未执行。
  • INFLIGHT:表示action当前正在执行。
  • COMPLETED:表示timeline上的action已经完成。

1.4. 两个时间概念

  • Arrival time: 数据到达 Hudi 的时间,commit time。
  • Event time: record 中记录的时间。

        上图中采用时间(小时)作为分区字段,从 10:00 开始陆续产生各种 commits,10:20 来了一条 9:00 的数据,根据event time该数据仍然可以落到 9:00 对应的分区,通过 timeline 直接消费 10:00 (commit time)之后的增量更新(只消费有新 commits 的 group),那么这条延迟的数据仍然可以被消费到。

2. 文件布局(File Layout)

2.1. Hudi表的文件结构

Hudi将一个表映射为如下文件结构

2.2. Hudi存储的两个部分

  • 元数据:.hoodie目录对应着表的元数据信息,包括表的版本管理(Timeline)、归档目录(存放过时的instant也就是版本),一个instant记录了一次提交(commit)的行为、时间戳和状态,Hudi以时间轴的形式维护了在数据集上执行的所有操作的元数据;
  • 数据:和hive一样,以分区方式存放数据;分区里面存放着Base File(.parquet)和Log File(.log.*);

2.3. Hudi的具体文件说明

(1)Hudi将数据表组织成分布式文件系统基本路径(basepath)下的目录结构

(2)表被划分为多个分区,这些分区是包含该分区的数据文件的文件夹,非常类似于Hive表

(3)在每个分区中,文件被组织成文件组,由文件ID唯一标识

(4)每个文件组包含几个文件片(FileSlice)

(5)每个文件片包含:

  • 一个基本文件(.parquet):在某个commit/compaction即时时间(instant time)生成的(MOR可能没有)
  • 多个日志文件(.log.*),这些日志文件包含自生成基本文件以来对基本文件的插入/更新(COW没有)

(6)Hudi采用了多版本并发控制(Multiversion Concurrency Control, MVCC)

  • compaction操作:合并日志和基本文件以产生新的文件片
  • clean操作:清除不使用的/旧的文件片以回收文件系统上的空间

(7)Hudi的base file(parquet 文件)在 footer 的 meta 去记录了 record key 组成的 BloomFilter,用于在 file based index 的实现中实现高效率的 key contains 检测。只有不在 BloomFilter 的 key 才需要扫描整个文件消灭假阳。

(8)Hudi 的 log (avro 文件)是自己编码的,通过积攒数据 buffer 以 LogBlock 为单位写出,每个 LogBlock 包含 magic number、size、content、footer 等信息,用于数据读、校验和过滤。

3. 索引(Index)

3.1. 原理

        Hudi通过索引机制提供高效的upserts,具体是将给定的hoodie key(record key + partition path)与文件id(文件组)建立唯一映射。这种映射关系,数据第一次写入文件后保持不变,所以,一个 FileGroup 包含了一批 record 的所有版本记录。Index 用于区分消息是 INSERT 还是 UPDATE。

        Hudi 为了消除不必要的读写,引入了索引的实现。在有了索引之后,更新的数据可以快速被定位到对应的 File Group。上图为例,白色是基本文件,黄色是更新数据,有了索引机制,可以做到:避免读取不需要的文件、避免更新不必要的文件、无需将更新数据与历史数据做分布式关联,只需要在 File Group 内做合并。

3.2. 索引选项

Index类型原理优点缺点
Bloom Index默认配置,使用布隆过滤器来判断记录存在与否,也可选使用record key的范围裁剪需要的文件效率高,不依赖外部系统,数据和索引保持一致性因假阳性问题,还需回溯原文件再查找一遍
Simple Indexupdate/delete操作的新数据和老数据进行join实现最简单,无需额外的资源性能比较差
HBase Indexindex存放在HBase里面。在插入 File Group定位阶段所有taskHBase发送 Batch Get 请求,获取 Record Key Mapping 信息对于小批次的keys,查询效率高需要外部的系统,增加了运维压力
Flink State-based IndexHUDI 在 0.8.0 版本中实现的 Flink witer,采用了 Flink 的 state 作为底层的 index 存储,每个 records 在写入之前都会先计算目标 bucket ID。不同于 BloomFilter Index,避免了每次重复的文件 index 查找 

注意:Flink只有一种state based index(和bucket_index),其他index是Spark可选配置。

3.3. 全局索引与非全局索引

        全局索引:全局索引在全表的所有分区范围下强制要求键的唯一性,也就是确保对给定的键有且只有一个对应的记录。全局索引提供了更强的保证,但是随着表增大,update/delete 操作损失的性能越高,因此更适用于小表。

        非全局索引:默认的索引实现,只能保证数据在分区的唯一性。非全局索引依靠写入器为同一个记录的update/delete提供一致的分区路径,同时大幅提高了效率,更适用于大表。
从index的维护成本和写入性能的角度考虑,维护一个global index的难度更大,对写入性能的影响也更大,所以需要non-global index。

        HBase索引本质上是一个全局索引,bloom和simple index都有全局选项(hoodie.index.type=GLOBAL_BLOOM 和 hoodie.index.type=GLOBAL_SIMPLE)

3.4. 索引的选择策略

3.4.1. 对事实表的延迟更新

        许多公司会在NoSQL数据存储中存放大量的交易数据。例如共享出行的行程表、股票买卖记录的表、和电商的订单表。这些表通常一直在增长,且大部分的更新随机发生在较新的记录上,而对旧记录有着长尾分布型的更新。这通常是源于交易关闭或者数据更正的延迟性。换句话说,大部分更新会发生在最新的几个分区上而小部分会在旧的分区。

        对于这样的作业模式,布隆索引就能表现地很好,因为查询索引可以靠设置得当的布隆过滤器来裁剪很多数据文件。另外,如果生成的键可以以某种顺序排列,参与比较的文件数会进一步通过范围裁剪而减少。Hudi用所有文件的键域来构造区间树,这样能来高效地依据输入的更删记录的键域来排除不匹配的文件。

        为了高效地把记录键和布隆过滤器进行比对,即尽量减少过滤器的读取和均衡执行器间的工作量,Hudi缓存了输入记录并使用了自定义分区器和统计规律来解决数据的偏斜。有时,如果布隆过滤器的假阳性率过高,查询会增加数据的打乱操作。Hudi支持动态布隆过滤器(设置hoodie.bloom.index.filter.type=DYNAMIC_V0)。它可以根据文件里存放的记录数量来调整大小从而达到设定的假阳性率。

3.4.2. 对事件表的去重

        事件流无处不在。从Apache Kafka或其他类似的消息总线发出的事件数通常是事实表大小的10-100倍。事件通常把时间(到达时间、处理时间)作为首类处理对象,比如物联网的事件流、点击流数据、广告曝光数等等。由于这些大部分都是仅追加的数据,插入和更新只存在于最新的几个分区中。由于重复事件可能发生在整个数据管道的任一节点,在存放到数据湖前去重是一个常见的需求。

        总的来说,低消耗去重是一个非常有挑战的工作。虽然可以用一个键值存储来实现去重(即HBase索引),但索引存储的消耗会随着事件数增长而线性增长以至于变得不可行。事实上,有范围裁剪功能的布隆索引是最佳的解决方案。我们可以利用作为首类处理对象的时间来构造由事件时间戳和事件id(event_ts+event_id)组成的键,这样插入的记录就有了单调增长的键。这会在最新的几个分区里大幅提高裁剪文件的效益。

3.4.3. 对维度表的随机更删

        正如之前提到的,如果范围比较不能裁剪许多文件的话,那么布隆索引并不能带来很好的效益。在这样一个随机写入的作业场景下,更新操作通常会触及表里大多数文件从而导致布隆过滤器依据输入的更新对所有文件标明阳性。最终会导致,即使采用了范围比较,也还是检查了所有文件。使用简单索引对此场景更合适,因为它不采用提前的裁剪操作,而是直接和所有文件的所需字段连接。如果额外的运维成本可以接受的话,也可以采用HBase索引,其对这些表能提供更加优越的查询效率。
        当使用全局索引时,也可以考虑通过设置hoodie.bloom.index.update.partition.path=true或hoodie.simple.index.update.partition.path=true来处理 的情况;例如对于以所在城市分区的用户表,会有用户迁至另一座城市的情况。这些表也非常适合采用Merge-On-Read表型。

4. 表类型(Table Types)

4.1. Copy On Write

        在COW表中,只有数据文件/基本文件(.parquet),没有增量日志文件(.log.*)。对每一个新批次写入都将创建相应数据文件的新版本(新的FileSlice),新版本文件包括旧版本文件的记录以及来自传入批次的记录(全量最新)。

假设我们有 3 个文件组,其中包含如下数据文件。

我们进行一批新的写入,在索引后,我们发现这些记录与File group 1 和File group 2 匹配,然后有新的插入,我们将为其创建一个新的文件组(File group 4)。

        因此data_file1 和 data_file2 都将创建更新的版本,data_file1 V2 是data_file1 V1 的内容与data_file1 中传入批次匹配记录的记录合并。由于在写入期间进行合并,COW 会产生一些写入延迟。但是COW 的优势在于它的简单性,不需要其他表服务(如压缩),也相对容易调试。

4.2. Merge On Read

        MOR表中,包含列存的基本文件(.parquet)和行存的增量日志文件(基于行的avro格式,.log.*)。顾名思义,MOR表的合并成本在读取端。因此在写入期间我们不会合并或创建较新的数据文件版本。标记/索引完成后,对于具有要更新记录的现有数据文件,Hudi 创建增量日志文件并适当命名它们,以便它们都属于一个文件组。

        读取端将实时合并基本文件及其各自的增量日志文件。每次的读取延迟都比较高(因为查询时进行合并),所以 Hudi 使用压缩机制来将数据文件和日志文件合并在一起并创建更新版本的数据文件。

        用户可以选择内联或异步模式运行压缩。Hudi也提供了不同的压缩策略供用户选择,最常用的一种是基于提交的数量。例如可以将压缩的最大增量日志配置为 4。这意味着在进行 4 次增量写入后,将对数据文件进行压缩并创建更新版本的数据文件。压缩完成后,读取端只需要读取最新的数据文件,而不必关心旧版本文件。

MOR表的写入行为,依据 index 的不同会有细微的差别:

  • 对于 BloomFilter 这种无法对 log file 生成 index 的索引方案,对于 INSERT 消息仍然会写 base file (parquet format),只有 UPDATE 消息会 append log 文件(因为 base file 已经记录了该 UPDATE 消息的 FileGroup ID)。
  • 对于可以对 log file 生成 index 的索引方案,例如 Flink writer 中基于 state 的索引,每次写入都是 log format,并且会不断追加和 roll over。

4.3. COW与MOR的对比

CopyOnWrite

MergeOnRead

数据延迟

查询延迟

Update(I/O) 更新成本

高(重写整个Parquet文件)

低(追加到增量日志)

Parquet文件大小

低(更新成本I/O高)

较大(低更新成本)

写放大

低(取决于压缩策略)

5. 查询类型(Query Types)

5.1. Snapshot Queries

快照查询,可以查询指定commit/delta commit即时操作后表的最新快照。

在读时合并(MOR)表的情况下,它通过即时合并最新文件片的基本文件和增量文件来提供近实时表(几分钟)。

对于写时复制(COW),它可以替代现有的parquet表(或相同基本文件类型的表),同时提供upsert/delete和其他写入方面的功能,可以理解为查询最新版本的Parquet数据文件。

下图是COW的快照查询:

5.2. Incremental Queries

增量查询,可以查询给定commit/delta commit即时操作以来新写入的数据。有效的提供变更流来启用增量数据管道。

5.3. Read Optimized Queries

读优化查询,可查看给定的commit/compact即时操作的表的最新快照。仅将最新文件片的基本/列文件暴露给查询,并保证与非Hudi表相同的列查询性能。

下图是MOR表的快照查询与读优化查询的对比:

Read Optimized Queries是对Merge On Read表类型快照查询的优化。

Snapshot

Read Optimized

数据延迟

查询延迟

高(合并列式基础文件+行式增量日志文件)

(原始列式基础文件)

5.4. 不同表支持的查询类型

6. Compaction

(1)没有 base file:走 copy on write insert 流程,直接 merge 所有的 log file 并写 base file

(2)有 base file:走 copy on write upsert 流程,先读 log file 建 index,再读 base file,最后读 log file 写新的 base file

Flink 和 Spark streaming 的 writer 都可以 apply 异步的 compaction 策略,按照间隔 commits 数或者时间来触发 compaction 任务,在独立的 pipeline 中执行。


注:其他Hudi相关文章链接由此进 ->  Hudi文章汇总 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/118209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cocos 引擎生态部负责人李阳:己之所欲,可施于人,希望通过生态促进国内引擎技术发展

前言 “小小的身体,大大的能量,这个应该是我对大表姐最直接的感觉,在她娇小的身躯里蕴含了无限的精力和潜力,很像漫威里的神奇女侠,作为一个具备冒险精神的非典型程序员,大表姐热爱的体育活动都是很具挑战…

大数据系列——什么是ClickHouse?ClickHouse有什么用途?

目录 一、什么是ClickHouse 二、ClickHouse有什么用途 三、ClickHouse的不足 四、适用场景 五、ClickHouse特点 六、ClickHouse VS MySQL 七、类SQL 语句 八、核心概念 一、什么是ClickHouse clickHouse是俄罗斯的 Yandex 公司于 2016 年开源的列式存储数据库&#x…

win11系统用户名称为中文导致文件夹出现繁体字文件夹、系统路径配置错误修改教程(博主亲测,基于win11,系统文件保留)

写在前面:很多人在拿到新电脑激活那会,命名就是简单的中文,但是中文命名电脑系统名称,会导致系统用户文件夹自动命名为中文,在后期使用中会导致c盘系统用户文件夹下面出现不知名繁体字文件夹,甚至有的朋友会…

终难逃一阳

阳了,抗原试剂显示我阳了。每天都带口罩的我还是未能逃过此劫。真是覆巢之下,焉有完卵。 ​ 1.背景 12月初国家逐步放开防疫,随之而来的就是奥秘克戎肆虐全国。身边同事和朋友一个接着一个倒下,朋友圈里更是哀嚎一片。好在专家…

《CSAPP》笔记——链接、异常控制流、虚拟内存

文章目录传送门链接基础链接器的意义编译器驱动程序静态链接ELF目标文件格式可重定位目标文件符号和符号表链接过程符号解析解析规则静态链接库带有静态链接库的解析过程重定位重定位条目重定位节重定位符号引用重定位相对引用重定位绝对引用加载可执行目标文件动态链接共享库库…

Kafka 消费者组开发

Kafka consumer - 消费者组 上一篇文章学习到kafka消费者、消费者组之间处理消息的差异,总结起来就是: 同一个消费组的不同消费实例 共同消费topiic的消息, 一个消息只会消费一次; 也叫做集群消费同一个消息被不同的消费组同时消费&#xf…

机器学习基石1(ML基本概念和VC dimension)

文章目录一、什么是机器学习?二、什么时候可以使用机器学习?三、感知机perceptron四、机器学习的输入形式五、机器真的可以学习吗?六、vc dimension一、什么是机器学习? 其实第一个问题和第二个问题是穿插到一块儿回答的,首先机器学习要解决的是常规的…

RedisTemplate操作redis

目录 Redis Repositories方式 a、启用 Repository 功能 b、注解需要缓存的实体 c、创建一个 Repository 接口 d、测试类中测试 Redis Repositories方式 Spring Data Redis 从 1.7 开始提供 Redis Repositories ,可以无缝的转换并存储 domain objects&#xff0…

TOPSIS法(熵权法)(模型+MATLAB代码)

TOPSIS可翻译为逼近理想解排序法,国内简称为优劣解距离法 TOPSIS法是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的距离 一、模型介绍 极大型指标(效益型指标) &#xff…

OR-Tools工具介绍以及实战(从入门到超神Python版)

目录前言0、安装一、什么是优化问题?1-1、优化问题介绍1-2、举例1-2-1、导入所需要的库1-2-2、声明求解器1-2-3、创建变量1-2-4、定义约束条件1-2-5、定义目标函数1-2-6、调用求解器,并且显示结果。二、python有关于各种优化问题示例2-1、简单的线性编程…

AlexNet 深度学习奠基作之一(1)

2012年发表 imagenet 一百二十万的图片 1000个种类 cv 对于刷榜 是非常在意的 AlexNet 有六千万的参数,和65000的神经元 为了减少过拟合 我们使用了dropout 很work 很有效 而且 这篇文章没有conclusion 只有 讨论 当他发现 从5个层里面去掉一个 performence会降…

ubuntu设置core文件

长久不写代码,突然发现ubuntu当前运行目录下没有生成core文件,记录如下,避免下次重找。 1、首先开启core文件权限: ulimit -c 如果结果为0, 则表示没有开启,需要开启,如下: 通过u…

【Linux】Linux系统SSH客户端断开后保持进程继续运行配置方法;Python等脚本在终端后台运行的方法

0. 概述 在Linux系统中,通常我们在执行一些运行时间比较长的任务时,必须等待执行完毕才能断开SSH连接或关闭客户端软件,否则可能会导致执行中断。本文介绍几种保障程序在用户退出登录后持续运行的方法。 一、方法 1. 使用nohup执行 nohup…

网络编程 事件选择模型

目录 1.概念分析 2.事件选择代码逻辑 1.WSACreateEvent函数 2.WSACloseEvent函数 3.WSAEventSelect函数 4.WSAWaitForMultipleEvents()函数 5.WSAEnumNetworkEvents函数 事件分类 3.##模型代码样例 1.概念分析 本质上是操作系统处理用户行为,详细如下 事件选…

目标检测之YOLOv5算法分析

YOLOv5共有5个版本的网络模型及其权重文件,即(n,s,m,l,x)。 (下图来自github上yolov5官方开源项目的性能截图) 其中n,s,m,l,x网络模型结构如出一辙,差异在参数上。另外的n6,s6,m6,l6,x6模型是对于更大分辨…

人生黄金十年,你有考虑来社科院与杜兰大学金融管理硕士项目汲取能量吗

在人生长河中,你觉得黄金的十年是哪个阶段呢?在一篇文章中看到人生最宝贵的十年,就是30岁到40岁这十年,一切都未确定,一切都还有机会,这个年龄段,寸阴寸金,流金年华,应该…

FFmpeg学习笔记--视频传输的基本概念

目录 1--容器(container)和文件(file) 2--媒体流(stream) 3--数据帧(frame)和数据包(packet): 4--编解码器(Codec) 5…

7万人随访发现,每周高强度运动15分钟,死亡风险降低24%

*仅供医学专业人士阅读参考我们已经知道,无论是日常规律运动,还是周末集中一两天运动,只要每周能完成至少75-150分钟的高强度有氧运动,都可以降低全因死亡率和特定原因死亡率[1]。每周300-600分钟中强度运动或150-300分钟高强度运…

RocketMQ原理篇

文章目录broker与NameServerMessageQueue与Topic的关系生产者、消费者写入读取 消息CommitLog生产者消费者组broker与NameServer 基于 Dledger 实现 RocketMQ 高可用自动切换 broker 会每隔 30 秒向 NameServer 发送一个的心跳 ,NameServer 收到一个心跳 会更新对…

kafka再浅析

在日常开发中,经常使用kafka,对它是既熟悉又陌生,下面继续聊,继续总结。 1、消息中间件 分布式消息是一种通信机制,和RPC、HTTP不一样,消息中间件采用分布式中间代理的方式进行通信。采用消息中间件后&…