【大数据】详解 AVRO 格式

详解 AVRO 格式

  • 1.Avro 介绍
  • 2.schema
    • 2.1 原始类型
    • 2.2 复杂类型
      • 2.2.1 Records
      • 2.2.2 Enums
      • 2.2.3 Arrays
      • 2.2.4 Maps
      • 2.2.5 Unions
      • 2.2.6 Fixed
  • 3.Avro 的文件存储格式
    • 3.1 数据编码
      • 3.1.1 原始类型
      • 3.1.2 复杂类型
    • 3.2 存储格式
    • 3.3 存储格式
  • 4.小结

1.Avro 介绍

Apache Avro 是 Hadoop 中的一个子项目,也是一个数据序列化系统,其数据最终以二进制格式,采用行式存储的方式进行存储。

Avro提供了:

  • ✅ 丰富的数据结构。
  • ✅ 可压缩、快速的二进制数据格式。
  • ✅ 一个用来存储持久化数据的容器文件。
  • ✅ 远程过程调用。
  • ✅ 与动态语言的简单集成,代码生成不需要读取或写入数据文件,也不需要使用或实现 RPC 协议。代码生成是一种可选的优化,只值得在静态类型语言中实现。

基于以上这些优点,Avro 在 Hadoop 体系中被广泛使用。除此之外,在 Hudi、Iceberg 中也都有用到 Avro 作为元数据信息的存储格式。

2.schema

Avro 依赖 schema模式)来实现数据结构的定义,schema 通过 json 对象来进行描述表示,具体表现为:

  • 一个 json 字符串命名一个定义的类型。
  • 一个 json 对象,其格式为 {"type":"typeName" ... attributes ...},其中 typeName原始类型名称复杂类型名称
  • 一个 json 数组,表示嵌入类型的联合。

schema 中的类型由 原始类型(也就是 基本类型)(nullbooleanintlongfloatdoublebytesstring)和 复杂类型recordenumarraymapunionfixed)组成。

2.1 原始类型

原始类型包括如下几种:

  • null:没有值
  • boolean:布尔类型的值
  • int 32 32 32 位整形
  • long 64 64 64 位整形
  • float 32 32 32 位浮点
  • double 64 64 64 位浮点
  • bytes 8 8 8 位无符号类型
  • stringunicode 字符集序列

原始类型没有指定的属性值,原始类型的名称也就是定义的类型的名称,因此,schema 中的 "string" 等价于 {"type":"string"}

2.2 复杂类型

Avro 支持 6 种复杂类型:recordsenumsarraysmapsunionsfixed

2.2.1 Records

reocrds 使用类型名称 "record",并支持以下属性

  • name:提供记录名称的 json 字符串(必选)
  • namespace:限定名称的 json 字符串
  • doc:一个 json 字符串,为用户提供该模式的说明(可选)
  • aliases:字符串的 json 数组,为该记录提供备用名称
  • fields:一个 json 数组,罗列所有字段(必选),每个字段又都是一个 json 对象,并包含如下属性:
    • name:字段的名称(必选)
    • doc:字段的描述(可选)
    • type:一个 schema,定义如上
    • default:字段的默认值
    • order:指定字段如何影响记录的排序顺序,有效值为 "ascending"(默认值)、"descending""ignore"
    • aliases:别名

一个简单示例:

{
    "type": "record",
    "name": "LongList",
    "aliases": ["LinkedLongs"],
    "fields", [
        {"name": "value", "type": "long"},
        {"name": "next", "type": ["null", "LongList"]}
    ]
}

2.2.2 Enums

Enum 使用类型名称 enum,并支持以下属性

  • name:提供记录名称的 json 字符串(必选)
  • namespace:限定名称的 json 字符串
  • aliases:字符串的 json 数组,为该记录提供备用名称
  • doc:一个 json 字符串,为用户提供该模式的说明(可选)
  • symbols:一个 json 数组,以 json 字符串的形式列出符号。在枚举中每个符号必须唯一,不能重复,每个符号都必须匹配正则表达式 "[A-Za-z_][A-Za-z0-9_]*"
  • default:该枚举的默认值。

示例:

{
    "type": "enum",
    "name": "Suit",
    "symbols": ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
}

2.2.3 Arrays

  • item:数组中元素的 schema

一个例子:声明一个 valuestringarray

{
    "type": "array",
    "items": "string",
    "default": []
}

2.2.4 Maps

  • valuesmap 的值(value)的 schema,其 key 被假定为字符串

一个例子:声明一个 valuelong 类型,(key 类型为 string)的 map

{
    "type": "map",
    "values": "long",
    "default": {}
}

2.2.5 Unions

union 使用 json 数组表示,例如 [null, "test"] 声明一个模式,它可以是空值或字符串。

需要注意的是:当为 union 类型的字段指定默认值时,默认值的类型必须与 union 第一个元素匹配,因此,对于包含 "null"union,通常先列出 "null",因为此类型的 union 的默认值通常为空。

另外,union 不能包含多个相同类型的 schema,类型为 recordfixedenum 除外。

2.2.6 Fixed

Fixed 使用类型名称 "fixed" 并支持以下属性:

  • name:提供记录名称的 json 字符串(必选)
  • namespace:限定名称的 json 字符串
  • aliases:字符串的 json 数组,为该记录提供备用名称
  • doc:一个 json 字符串,为用户提供该模式的说明(可选)
  • size:一个整数,指定每个值的字节数(必须)

例如,16 字节的数可以声明为:

{
    "type": "fixed",
    "name": "md5",
    "size": 16
}

3.Avro 的文件存储格式

3.1 数据编码

3.1.1 原始类型

  • 对于 null 类型:不写入内容,即 0 字节长度的内容表示。
  • 对于 boolean 类型:以 1 字节的 0 或 1 来表示 falsetrue
  • 对于 intlong:以 zigzag 的方式编码写入。
  • 对于 float:固定 4 字节长度,先通过 floatToIntBits 转换 32 位整数,然后按小端编码写入。
  • 对于 double:固定 8 字节长度,先通过 doubleToLongBits 转换为 64 位整型,然后按小端编码写入。
  • 对于 bytes:先写入长度(采用 zigzag 编码写入),然后是对应长度的二进制数据内容。
  • 对于 string:同样先写入长度(采用 zigzag 编码写入),然后再写入字符串对应 utf8 的二进制数据。

3.1.2 复杂类型

  • 对于 enums:只需要将 enum 的值所在的 Index 作为结果进行编码即可,例如,枚举值为 ["A","B","C","D"],那么 0 就表示 "A",3 表示 "D"
  • 对于 maps:被编码为一系列的块。每个块由一个长整数的计数表示键值对的个数(采用 zigzag 编码写入),其后是多个键值对,计数为 0 的块表示 map 的结束。每个元素按照各自的 schema 类型进行编码。
  • 对于 arrays:与 map 类似,同样被编码为一系列的块,每个块包含一个长整数的计数,计数后跟具体的数组项内容,最后以 0 计数的块表示结束。数组项中的每个元素按照各自的 schema 类型进行编码。
  • 对于 unions:先写入 long 类型的计数表示每个 value 值的位置序号(从零开始),然后再对值按对应 schema 进行编码。
  • 对于 records:直接按照 schema 中的字段顺序来进行编码。
  • 对于 fixed:使用 schema 中定义的字节数对实例进行编码。

3.2 存储格式

在一个标准的 avro 文件中,同时存储了 schema 的信息,以及对应的数据内容。具体格式由三部分组成:

  • 魔数:固定 4 字节长度,内容为字符 'O''b''j',以及版本号标识,通常为 1 1 1

  • 元数据信息:文件的元数据属性,包括 schema、数据压缩编码方式等。整个元数据属性以一个 map 的形式编码存储,每个属性都以一个 KV 的形式存储,属性名对应 key,属性值对应 value,并以字节数组的形式存储。最后以一个固定 16 字节长度的随机字符串标识元数据的结束。

  • 数据内容:而数据内容则由一个或多个数据块构成。每个数据块的最前面是一个 long 型(按照 zigzag 编码存储)的计数表示该数据块中实际有多少条数据,后面再跟一个 long 型的计数表示编码后的( N N N 条)数据的长度,随后就是按照编码进行存储的一条条数据,在每个数据块的最后都有一个 16 字节长度的随机字符串标识块的结束。

整体存储内容如下图所示:
在这里插入图片描述

3.3 存储格式

我们通过一个实际例子来对照分析下。

首先定义 schema 的内容,具体为 4 个字段的表,名称(字符串)、年龄(整型)、技能(数组)、其他(map 类型),详细如下所示:

{
    "type":"record",
    "name":"person",
    "fields": [
        {
            "name": "name",
            "type": "string"
        },
        {
            "name": "age",
            "type": "int"
        },
        {
            "name": "skill",
            "type": {
                "type":"array",
                "items": "string"
            }
        },
        {
            "name": "other",
            "type": {
                "type": "map",
                "values": "string"
            }
        }
    ]
}

再按照上面的 schema 定义两条数据(person.json):

{"name":"hncscwc","age":20,"skill":["hadoop","flink","spark","kafka"],"other":{"interests":"basketball"}}
{"name":"tom","age":18, "skill":["java","scala"],"other":{}}

通过 avro-tools 可以生成一个 avro 文件:

java -jar avro-tools-1.7.4.jar fromjson --schema-file person.avsc person.json > person.avro

通过二进制的方式查看生成的 avro 文件内容:
在这里插入图片描述
另外,对于一个已存在的文件,也可以通过 avro-tools 工具查看 schema 内容、数据内容。

[root@localhost avro]$ java -jar avro-tools-1.7.4.jar getschema ./person.avro
{
  "type" : "record",
  "name" : "person",
  "fields" : [ {
    "name" : "name",
    "type" : "string"
  }, {
    "name" : "age",
    "type" : "int"
  }, {
    "name" : "skill",
    "type" : {
      "type" : "array",
      "items" : "string"
    }
  }, {
    "name" : "other",
    "type" : {
      "type" : "map",
      "values" : "string"
    }
  } ]
}
[root@localhost avro]$ java -jar avro-tools-1.7.4.jar tojson ./person.avro
{"name":"hncscwc","age":20,"skill":["hadoop","flink","spark","kafka"],"other":{"interests":"basketball"}}
{"name":"tom","age":18,"skill":["java","scala"],"other":{}}

4.小结

本文对 avro 的格式定义、编码方式、以及实际存储的文件格式进行了详细说明,最后也以一个实际例子进行了对照说明。另外, 在官网中还涉及 rpc 的使用、mapreduce 的使用,这里就没有展开说明,有兴趣的可移步官网进行查阅。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【rabbitMQ】声明队列和交换机

上一篇:springboot整合rabbitMQ模拟简单收发消息 https://blog.csdn.net/m0_67930426/article/details/134904766?spm1001.2014.3001.5501 相关配置环境参考上篇 springAMQP提供了几个类用来声明声明队列,交换机及其绑定关系 声明队列,…

经典策略筛选-20231213

策略1: 龙头战法只做最强:国企改革 ----四川金顶 1、十日交易内出现 涨停或 (涨幅大于7个点且量比大于3) 2、JDK MACD RSI OBV LWR MTM 六指标共振 3、均线多头 4、 筹码峰 (锁仓) 5、现价> 五日均…

C语言之文件操作(上)

C语言之文件操作(上) 文章目录 C语言之文件操作(上)1. 什么是⽂件?1.1 程序⽂件1.2 数据⽂件1.3 ⽂件名 2. ⼆进制⽂件和⽂本⽂件3. ⽂件的打开和关闭3.1 流和标准流3.1.1 流3.1.2 标准流 4. ⽂件指针5. 文件的打开与关…

什么是连接池?如何确认连接池的大小?

对于我们编写的几乎每个网络或移动应用程序来说,其底层的关键组件之一就是数据库。对于编写使用数据库且高性能且资源高效的应用程序,必须处理一项关键资源,但与 CPU、内存等不同,它通常不是很明显。该资源是数据库连接。 什么是…

调用Win10隐藏的语音包

起因 在做一个文本转语音的Demo的时候,遇到了语音包无法正确被Unity识别的问题。明明电脑上安装了语音包但是代码就是识别不出来 原因 具体也不是非常清楚,但是如果语言包是在的话,大概率是Win10系统隐藏了。 确定语言包 首先查看%windi…

VLAN详细学习

文章目录 VLAN概念VLAN种类端口VLAN工作原理以太网的三种链路类型配置 VLAN概念 一种讲局域网设备从逻辑上划分为一个个网段,从而实现虚拟网络的一种技术,这一技术主要应用于交换机中。Vlan技术是技术在以太网帧的基础上增加vlan头,用VLAN I…

云计算大屏,可视化云计算分析平台(云实时数据大屏PSD源文件)

大屏组件可以让UI设计师的工作更加便捷,使其更高效快速的完成设计任务。现分享可视化云分析系统、可视化云计算分析平台、云实时数据大屏的大屏Photoshop源文件,开箱即用! 若需 更多行业 相关的大屏,请移步小7的另一篇文章&#…

代码随想录算法训练营第50天| 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV

JAVA代码编写 123.买卖股票的最佳时机III 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 **注意:**你不能同时参与多笔交易(你必须在再次购买前出…

记录 | ubuntu上安装fzf

在 ubuntu 上采用命令行安装 fzf 的方式行不通 指的是采用下面的方式行不通: sudo apt install fzf # 行不通 sudo snap install fzf --classic # 行不通正确的安装方式是: ● 到 fzf 的 git 仓库:https://github.com/junegunn/fzf/re…

aardio网页组件:webPageOperation

webPageOperation是webview的初步封装,用来网页填表、操作网页。可操作web.form、web.view、web.view2等浏览器组件。 使用方法 首先把webPageOperation.aardio(源码在后面)放到~\lib\godking目录下,然后新建窗口项目&#xff…

Leetcode—10.正则表达式匹配【困难】

2023每日刷题&#xff08;五十八&#xff09; Leetcode—10.正则表达式匹配 算法思想 参考题解 实现代码 class Solution { public:bool isMatch(string s, string p) {int m s.size(), n p.size();vector<vector<bool>> dp(m 1, vector<bool>(n …

基于单片机智能循迹小车仿真设计

**单片机设计介绍&#xff0c;基于单片机智能循迹小车仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能循迹小车是一种通过传感器检测地面情况&#xff0c;并根据设定的规则进行动作控制的机器人。它使用…

信号量机制及信号量实现进程同步、互斥、前驱关系

进程互斥的四种软件实现万式&#xff08;单标志法、双标志先检查、双标志后检查、Peterson算法)进程互斥的三种硬件实现方式&#xff08;中断屏蔽方法、TS/TSL指令、Swap/XCHG指令&#xff09; 1.在双标志先检查法中&#xff0c;进入区的“检查”、“上锁”操作无法一气呵成&am…

性能测试、负载测试、压力测试之间的差异!

1、什么是性能测试 性能测试是一种用于确定计算机、网络或设备速度的测试。它通过在不同的负载场景中传递不同的参数来检查系统组件的性能。 2、什么是负载测试 负载测试是在任何应用程序或网站上模拟实际用户负载的过程。它检查应用程序在正常和高负载期间的行为。当开发项目…

CAN 三: STM32 CAN相关寄存器介绍

1、寄存器列表&#xff08;F1/F4/F7&#xff09; 寄存器名称作用CAN_MCRCAN主控制寄存器主要负责CAN工作模式的配置CAN_BTR位时序寄存器用来设置分频/TBS1/TBS2/TSWJ等参数&#xff0c;设置测试模式CAN_(T/R)IxR标识符寄存器存放(待发送/接收)的报文ID、扩展ID、IDE位及RTR位C…

[c]零钱兑换

题目比较简单&#xff0c;看答案就能看懂什么意思 #include<stdio.h> int main() {int count 0;int n;scanf("%d", &n);for (int i 0; i < n; i){for (int k 0; k <n/2; k){for (int j 0; j < n/5 ; j){if (i 2 * k 5 * j n){count;}}}}p…

ZXing生成二维码

&#x1f60a; 作者&#xff1a; 瓶盖子io &#x1f496; 主页&#xff1a; 瓶盖子io-CSDN博客 1.介绍 Android Zxing框架 生成二维码扫码功能;ZXing是一个开源的类库&#xff0c;是用Java编写的多格式的1D / 2D条码图像处理库&#xff0c;使用ZXing可以生成、识别QR Code(…

Servlet 的初步学习

前言 咱们最核心的目标是基于tomcat编程, 做出网站来 ~~ 基于tomcat进行网站后端的开发. 网站后端, http服务器,肯定是需要针对http 协议进行一系列操作的. 幸运的是, tomcat,已经把这些http相关的底层操作,封装好了只需要调用tomcat给咱们提供的api即可 Servlet 是什么 Servl…

做数据分析为何要学统计学(6)——什么问题适合使用卡方检验?

卡方检验作为一种非常著名的非参数检验方法&#xff08;不受总体分布因素的限制&#xff09;&#xff0c;在工程试验、临床试验、社会调查等领域被广泛应用。但是也正是因为使用的便捷性&#xff0c;造成时常被误用。本文参阅相关的文献&#xff0c;对卡方检验的适用性进行粗浅…

基于Java8构建Docke镜像

基于Java8构建Docke镜像 搜索java8安装包 docker search java8 --no-trunc &#xff0c; --no-trunc展开描述信息 选择拉取 docker pull docker.io/mykro/java8-jre&#xff0c;为了减少磁盘占用&#xff0c;选择jre版本基础镜像 在宿主机创建文件夹iot&#xff0c;并把所需…