Hudi Log 文件格式与读写流程

2023-11-20

Hudi Log 文件格式与读写流程

背景

对 Hudi 有一定了解的读者应该知道,Hudi 有 COW 和 MOR 两种表类型。其中的 MOR 表会通过日志文件记录文件,写入一个 MOR 表后产生的文件可以观察到,一个 MOR 表数据存储在3种文件中:Log File(.*log.*),分区元数据(.hoodie_partition_metadata),数据文件(.*parquet)。期间查阅了大量的相关资料,发现发现鲜有文章对 Log 日志数据文件的具体内容与结构做详细的介绍。原因之一可能是:虽然 Log 文件使用了 Avro 序列化的行式存储,但其仅在对 records 的序列化时使用了原生 avro 的标准,文件其余部分的编码为 Hudi 自己的格式,进而导致其无法使用avro-tools.jar对其进行查看。本文介绍内容如下:

  • Log 文件读写流程
  • Log 文件结构分析

Log 文件读写流程

本文基于 Hudi 0.9.0 版本进行分析。形如Log File(.*log.*)的日志文件,由于无法直接使用工具查看内容,所以主要从源码的层面分析日志文件的写入和读取内容。

写入流程

整个写入流程的代码实现在:org.apache.hudi.common.table.log.HoodieLogFormatWriter#appendBlocks

for (HoodieLogBlock block: blocks) {
  long startSize = outputStream.size();

  // 1. Write the magic header for the start of the block
  outputStream.write(HoodieLogFormat.MAGIC);

  // bytes for header
  byte[] headerBytes = HoodieLogBlock.getLogMetadataBytes(block.getLogBlockHeader());
  // content bytes
  byte[] content = block.getContentBytes();
  // bytes for footer
  byte[] footerBytes = HoodieLogBlock.getLogMetadataBytes(block.getLogBlockFooter());

  // 2. Write the total size of the block (excluding Magic)
  outputStream.writeLong(getLogBlockLength(content.length, headerBytes.length, footerBytes.length));

  // 3. Write the version of this log block
  outputStream.writeInt(currentLogFormatVersion.getVersion());
  // 4. Write the block type
  outputStream.writeInt(block.getBlockType().ordinal());

  // 5. Write the headers for the log block
  outputStream.write(headerBytes);
  // 6. Write the size of the content block
  outputStream.writeLong(content.length);
  // 7. Write the contents of the data block
  outputStream.write(content);
  // 8. Write the footers for the log block
  outputStream.write(footerBytes);
  // 9. Write the total size of the log block (including magic) which is everything written
  // until now (for reverse pointer)
  // Update: this information is now used in determining if a block is corrupt by comparing to the
  //   block size in header. This change assumes that the block size will be the last data written
  //   to a block. Read will break if any data is written past this point for a block.
  outputStream.writeLong(outputStream.size() - startSize);

  // Fetch the size again, so it accounts also (9).
  sizeWritten +=  outputStream.size() - startSize;
}

总结为流程图如下:

截屏2021-12-25 上午11.47.38

从图中可以看出,写入内容逻辑比较清晰:

  1. 写入Magic,内容为#HUDI#
    • 拿到header,footer的字节数组。header/footer类型为Map。字节数组中会写入此Map的size,Map的Key(enum类型)的序号,Value为String类型
    • 拿到content的字节数组。会序列化records,字节数组中会写入log block version,records的数量和avro序列化后的records
  2. 写入block size,不包括Magic的6个字节。
  3. 写入log format version。
  4. 写入block type,为枚举类型,写入的是枚举的序号转化为字节数组。
  5. 写入header字节数组。
  6. 写入content length。
  7. 写入content字节数组。
  8. 写入footer字节数组。
  9. 写入block length,包括Magic的6个字节。
读取流程

整个读取流程的代码实现在:org.apache.hudi.common.table.log.HoodieLogFileReader#readBlock

总结为流程图如下:

截屏2021-12-25 上午11.48.24

在读取流程中,会涉及一些校验的动作:

  1. 在hasNext()方法中,读取Magic。
    • 校验Magic。不相等,抛CorruptedLogFileException异常;相等,返回true;EOF到达文件尾部,吃掉异常,返回false。
  2. 读block size。
    • 校验block是否损坏。方式为指针移动 block size减去long类型字节长度 的位置,读取block length,比较 block size与block length减去Magic字节长度 是否相等。不相等,createCorruptBlock;相等继续。
  3. 读log format version。
  4. 读block type。
  5. 读header。
  6. 读content length。
  7. 读content。
    • 不启用readBlockLazily,从内存度content;启用readBlockLazily,指针移动到content结束位置。
  8. 读footer。
  9. 读block length。

Log 文件结构分析

Hudi 中与日志文件有关类的继承关系可以看下图:截屏2021-12-25 下午1.00.38

可以看出,Log 文件的公共部分属性主要在HoodieLogBlock中进行定义,数据部分的属性主要在HoodieLogBlock中进行定义,数据部分content的序列化与反序列化实现在HoodieAvroDataBlock中定义。

从上述读写流程,也可以总结出 Log 文件结构:

截屏2021-12-25 上午10.50.23

  • Magic:#HUDI#,字节数组类型。
  • blcok size:除了Magic的6字节长度和自身long类型8字节长度,long类型。
  • log format version:日志格式版本,现在是1,int类型。
  • block type:本身是枚举类型,有COMMAND_BLOCK, DELETE_BLOCK, CORRUPT_BLOCK, AVRO_DATA_BLOCK, HFILE_DATA_BLOCK,这里为枚举的序号,int类型。
  • header:字节数组,本身是Map,转换为字节数组时会将map的size写入字节数组。map的Key为HeaderMetadataType类型,是个枚举,有INSTANT_TIME, TARGET_INSTANT_TIME, SCHEMA, COMMAND_BLOCK_TYPE,Value为String类型。
  • content length:content字节数组的长度,long类型。
  • content:字节数组。其中内容为,log block version,int类型;records number,int类型;records序列化的字节数组。
  • footer:字节数组,和header一样,本身是Map,现在版本还没有内容。
  • block length:block size 加上6(Magic的字节数组长度),long类型。

根据 Log 文件的读取逻辑,不难写出解析 Log 日志文件的程序代码。将 Log 文件解析出来后,可以观察到 block length 的数值相较于文件本身大小,相差了8个字节,这8个字节就是 block size 本身long类型的字节长度,进一步证明了上述分析的正确性

总结

至此,对 MOR 表的Log File(.*log.*)文件分析已经全部结束,文章着重分析了文件结构,对读写流程中额外的异常处理没有进一步深入。文中如有遗漏或错误,欢迎指出讨论。

若读完有所收获,欢迎点赞吖~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hudi Log 文件格式与读写流程 的相关文章

  • 中国齿轮行业发展状况与投资规划建议报告2022-2028年

    中国齿轮行业发展状况与投资规划建议报告2022 2028年 详情内容请咨询鸿晟信合研究院 全新修订 2022年2月 撰写单位 鸿晟信合研究研究 报告目录 第1章 齿轮行业发展环境分析 1 1 齿轮行业政策环境分析 1 1 1 齿轮行业相关政
  • 签约多方共建石嘴山智慧康养新模式

    5月13日 百度智能云与石嘴山市民政局 中国电信股份有限公司石嘴山分公司 中国银行股份有限公司石嘴山市分行 石嘴山市青鸟颐居养老服务有限公司在宁签订 石嘴山市智慧康养战略合作协议 将发挥各自优势 合力推进智慧康养产业高质量发展 提高智慧养老
  • SparkStreaming知识总结

    一 流式计算的概述 1 1 什么是流式计算 1 数据流与静态数据的区别 数据流指的就是不断产生的数据 是源源不断 不会停止 静态数据指的就是存储在磁盘中的固定的数据 2 流式计算的概念 就是对数据流进行计算 由于数据是炼苗不断的产生的 所以
  • 工业母机扶持政策汇总来了,国家-广东省-深圳市

    工业母机是指金属加工机床 简单来说 工业母机是制造机器的机器 它体现了国家综合实力的重要基础性产业 代表了工业发展水平 目前 我国的机床相对来说还不够成熟 很多技术以及零件设备都是从国外引进 缺乏自主产权 国家和地方政府出台各项政策鼓励 工
  • 用Excel做简单的数据分析

    一 使用的数据 1 做月销量的柱状图 按住Ctrl可跨区选中 1 选中数据 2 选择柱状图 一般柱状图都使用2D 3 为图加上数据标签 更加直观 2 以同样的方式做饼图 1 如图 一般饼图都是做3D的 3 求月销售额 单价 X 月销量 1
  • Spark on Kubernetes 与 Spark on Yarn 不完全对比分析

    前言 Apache Spark 是目前应用最广泛的大数据分析计算工具之一 它擅长于批处理和实时流处理 并支持机器学习 人工智能 自然语言处理和数据分析应用 随着 Spark 越来越受欢迎 使用量越来越大 狭义上的 Hadoop MR 技术栈
  • B站S11破亿直播在线稳定性保障秘籍——演讲实录

    英雄联盟 S11全球总决赛 决赛中国战队夺冠 赛事直播盛况空前 观赛人数破亿 B站作为英雄联盟2021全球总决赛直播独家版权方不仅在整个比赛过程中保证了直播整体总体运行的平稳 还抗住了超预期的流量 如此大型的直播活动 B站究竟是如何保障系统
  • Easy-Es核心功能深度介绍

    背景 近期随着项目开源后热度的不断上涨 越来越多小伙伴开始对框架核心功能感兴趣 今天就让我带大家深入源码和架构 一起探索Easy Es 简称EE 的核心功能是如何被设计和实现的 和众多ORM框架一样 EE最为核心的功能就是CRUD 增删改查
  • Hive Transaction(Hive 事务管理)

    Hive 事务在 Hive 3 得到增强 hive site xml 配置
  • Hudi和Kudu的比较

    与Kudu相比 Kudu是一个支持OLTP workload的数据存储系统 而Hudi的设计目标是基于Hadoop兼容的文件系统 如HDFS S3等 重度依赖Spark的数据处理能力来实现增量处理和丰富的查询能力 Hudi支持Increme
  • 2022深圳福田区专精特新小巨人企业申报条件,补贴50万

    深圳福田区专精特新小巨人企业申报后 可获得50万补贴 需要申报认证及补贴的企业 在中华人民共和国境内工商注册登记 连续经营3年以上并具有独立法人资格的中小企业 想要申报的企业 都需要在了解规则条件的基础上才能提前做好准备 用华夏泰科进行便捷
  • Hbase Sehll基本命令

    进入hbase shell命令 hbase shell 1 status 查看hbase运行状态 2 version 查看hbase版本 3 list 列出hbase所有的 表 4 创建表 create info member member
  • 第四章 Flume专题-日志采集工具

    一 Flume专题之组件及架构介绍 1 Flume概述 1 1 Flume定义 Flume是一种分布式的 高可靠的和高可用的服务 用于有效地收集 聚合和移动大量日志数据框架 Flume是一个简单灵活的基于流数据的体系结构 1 2 Flume
  • 中国智慧能源行业行情监测及未来动向规划预测报告2022-2028年

    中国智慧能源行业行情监测及未来动向规划预测报告2022 2028年 报告目录 第一章 智慧能源的基本概述 第二章 2021 2021年全球智慧能源产业发展分析 2 1 2021 2021年全球智慧能源产业发展综况 2 1 1 全球智慧能源网
  • kafka(三)重平衡

    历史文章 kafka 一 kafka的基础与常用配置 文章目录 一 kafka消费者组 二 重平衡 Rebalance 2 1 重平衡触发条件 2 2 重平衡策略 2 2 1 Range 平均分配 2 2 2 RoundRobin 轮询分配
  • pycharm如何连接数据库并往数据库插入内容

    1 创建connection对象 2 创建cursor对象 游标对象 主要用于操作数据库 3 执行查询 4 关闭cursor对象 5 关闭connection 首先要先安装pumysql库 pip install pymysql 连接测试
  • elasticsearch 安装教程

    一 jdk安装 es要求jdk版本在1 8以上 所以先安装jdk1 8 安装步骤 1 安装完Centos6 5的Base Server版会默认安装OpenJDK 首先需要删除OpenJDK 命令 rpm qa grep java 显示如下
  • 大数据简介

    预备篇 目录 知识 大数据简介 计算机单位 大数据的五个 v Hadoop Hadoop概述 Hadoop的历史 Hadoop三大发行版本 1 Apache Hadoop 2 Cloudera Hadoop 3 Hortonworks Ha
  • 如何保证数据产出质量简述

    如何保证数据产出质量简述 数据质量的评估 数据质量的保障 数据产出流程 机制 revire机制 数据质量保障中的工具 规则 SQLSCAN DQC 基线 数据质量的评估 数据质量可以从一下几个角度进行评估 完整性 完整性是指数据的记录和信息
  • ETL.NET 助力海量数据轻松处理

    ETL NET 助力海量数据轻松处理 什么是 ETL EtlT About ETL About EtlT 谈谈 ETL 作用 ETL 对企业的作用 ETL 对个人职业发展的作用 ETL NET 介绍

随机推荐

  • MQTT.fx连接、订阅、发布OneNet平台(新版)

    第一步 打开MQTT fx 点击设置按钮 第二步 命名的话随便起 中文英文皆可以 token的下载地址 https open iot 10086 cn doc v5 develop detail 242 第三步 token生成密码 时间戳转
  • 数据结构之链表增删查改(最详细注释和最清晰思路,附完整代码)

    PZK学数据结构之链表 史上最详细思路和代码注释 完整代码我放在最后面了 可以直接跑 方便大家cv编程 文章目录 PZK学数据结构之链表 史上最详细思路和代码注释 完整代码我放在最后面了 可以直接跑 方便大家cv编程 前言 一 链表是什么
  • target属性里_blank _self _top _parent区别

    blank 是指超链接连接的网页 是通过一个新的网页窗口打开 self的话 是指在本身这个网页窗口来打开新的网页链接 top与 self差不很大 但是如果你用了时 就会知道两者的差别了 因为如果你的超链接是 做在 上时 如果用 self 点
  • broken pipe

    1 broken pipe的字面意思是 管道破裂 broken pip的原因是该管道的读端被关闭 2 broken pipe经常发生socket关闭之后 或者其他的描述符关闭之后 的write操作中 3 发生broken pipe错误时 进
  • Redis—列表(List)、集合(Set)、哈希(Hash)、有序集合 Zset

    Redis 列表List 集合Set 哈希Hash 有序集合 Zset 列表List 单键多值 常用命令 数据结构 Redis 集合 Set 常用命令 数据结构 Redis 哈希 Hash 常用命令 数据结构 Redis 有序集合 Zset
  • ElasticSearch

    ElasticSearch 一 ES介绍 ES是一款基于倒排索引的NoSQL数据库 传统数据库对于模糊查询存在性能瓶颈 而ES更擅长与大数据量的模糊查询 ES在存储数据的时候会先将数据进行分词 将分词的结果作为索引存入数据库中 当进行查询时
  • eclipse和myeclipse下main方法找不到主类的一种情况

    经常碰到java的main函数无法加载的问题 很多人就会以为是eclipse大姨妈了 然后疯狂的clean 疯狂的重启 其实不然 我们找到java build path找到下面的地方 看看路径是否指向编译后的class 需要注意的是 在ma
  • Java服务端限制下载速度

    没有资源取之不尽用之不竭 服务器带宽有限 能限制一点算一点 最近在使用云存储openstack swift做文件存储下载 如题先上限速code private Long writeResponse HttpServletResponse r
  • js制作简易计算器

    实现2个输入框中输入整数后 点击第三个输入框能给出2个整数的加减乘除 提示 获取元素的值设置和获取方法为 例 赋值 document getElementById id value 1 取值 var document getElementB
  • oracle 建表 提示 ora-00955:名称已由现有对象使用.

    问题 oracle 执行 Create table 设备执行库房 设备id number 18 执行库房id number 18 提示 ora 00955 名称已由现有对象使用 但是执行 drop table 设备执行库房 却提示表或视图不
  • java生成随机数组_JAVA生成随机数组10个数字并求和

    JAVA生成随机数组10个数字并求和 本文最终结果大概是这样的 使用java技术随机生成10个数 然后填充一个数组并在消息框中显示数组内容 接着对数组求和输出 将结果显示在消息框中 设计思路 可以先用Math Random 1000生成10
  • hive-05-Execution Error, return code 3 from org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask

    hive命令行里执行了一句话 select from person join zhanghao on person zjhm zhanghao zjhm limit 100 就是两个表做连接查询 数据量大小一个是3千万 一个是3亿 结果报错
  • 【Transformer系列】深入浅出理解Transformer网络模型(综合篇)

    一 参考资料 The Illustrated Transformer 图解Transformer 完整版 Attention Is All You Need The Core Idea of the Transformer transfor
  • 【含源码】两种不同风格的圣诞树代码合集,其中还有可以改名字的圣诞树代码

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 前言 一年一度的圣诞节马上就要到了 看到好多程序员小伙伴已经开始炫耀自己制作的圣诞树了 今天就跟大家分享2种不同风格的圣诞树 附上完整代码 拿来即用可以按照自
  • Linux常用命令记录

    文章目录 1 软件安装 安装软件 来自源服务器 安装 deb软件 来自本地 deb文件 修复依赖关系 卸载软件 2 文件 文件夹操作 删除文件夹 移动文件 文件重命名 3 程序查看 处理 进程查看 查看端口占用情况 强制终止程序 4 解压文
  • 肖sir__mysql之单表__004

    mysql之单表 一 建表语句 1 show databases 查看所有的数据库 2 create databaes 数据库名 创建数据库 3 use 数据库名 指定使用数据库 4 show tables 5 创建表 格式 create
  • linux计算字符串个数,Linux 统计某个字符串个数的方法

    在 Linux 系统下 有时候 我们可能要对一个日志文件进行分析 比如 分析日志文件中某个单词或者某个特殊字符串出现了多少次 对于匹配统计 一般用到正则方法 下面总结了几个统计字符串个数的方法 方法一 使用 grep 命令 grep o 字
  • Python自动化测试 软件测试最全教程(附笔记),看完就可就业

    最近看到很多粉丝在后台私信我 叫我做一期Python自动化测试的教程 其实关于这个问题 我也早就在着手准备了 我录制了一整套完整的Python自动化测试的教程 都上传在B站上面 大家有兴趣的可以去看一下 Python自动化测试 手把手教你做
  • springboot不香吗?为什么还要使用springcloud

    1 为什么要使用springcloud 如果我们的服务需要调用另外的一个服务 当然可以通过url 加接口直接调用 但是如果url变动后 我们也要跟着修改 还有可能服务宕机我们也不知道 而且现在只有一个url不具备高可用性 就算有多个url
  • Hudi Log 文件格式与读写流程

    Hudi Log 文件格式与读写流程 背景 对 Hudi 有一定了解的读者应该知道 Hudi 有 COW 和 MOR 两种表类型 其中的 MOR 表会通过日志文件记录文件 写入一个 MOR 表后产生的文件可以观察到 一个 MOR 表数据存储