【大数据】详解 AVRO 格式

2023-12-14 00:12
文章标签 数据 详解 格式 avro

本文主要是介绍【大数据】详解 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 的使用,这里就没有展开说明,有兴趣的可移步官网进行查阅。

这篇关于【大数据】详解 AVRO 格式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/490451

相关文章

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

批量导入txt数据到的redis过程

《批量导入txt数据到的redis过程》用户通过将Redis命令逐行写入txt文件,利用管道模式运行客户端,成功执行批量删除以Product*匹配的Key操作,提高了数据清理效率... 目录批量导入txt数据到Redisjs把redis命令按一条 一行写到txt中管道命令运行redis客户端成功了批量删除k

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3