【大数据】详解 AVRO 格式

news2024/9/20 6:29:30

详解 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 的使用,这里就没有展开说明,有兴趣的可移步官网进行查阅。

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

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

相关文章

阿里云SMC迁移RedHat/CentOS 5 内核升级

阿里云SMC迁移RedHat/CentOS 5 内核升级 1. 起因 服务器需要迁移上阿里云,有几台服务器用的是Redhat 5.x,在使用SMC进行迁移时出现以下报错. [2023-12-13 09:50:55] [Error] Check System Info Failed, codeS16_111, msgGet OS Info Failed: [error] grub is too old for C…

Python——数据库操作

目录 (1)安装Flask-SQLAlchemy (2)使用Flask-SQLAlchemy操作数据库 (3)连接数据库 •创建数据表 •增加数据 •查询数据 •更新数据 •删除数据 Flask-SQLAlchemy是Flask中用于操作关系型数据库的扩展…

Linux中使用podman管理容器

本章主要介绍使用podman管理容器 了解什么是容器,容器和镜像的关系安装和配置podman拉取和删除镜像给镜像打标签导出和导入镜像创建和删除镜像数据卷的使用管理容器的命令使用普通用户管理容器 对于初学者来说,不太容易理解什么是容器,这里…

【Azure 架构师学习笔记】- Azure Databricks (3) - 再次认识DataBricks

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (2) -集群 前言 在对Databricks有了初步了解之后,如果要深入使用则需要对其进行更深层次的了解。 Databricks ADB 是一个统一的…

C# Winfrm 编写一个天气查看助手

#前言# 最近这个北方的天气啊经常下雪,让我想起来我上学时候写的那个天气预报小功能了,今天又复现了一下,哈哈哈,大家当个乐子看哈! 1.创建项目 2.添加引用 上图所示,下载所需天气预报标识,网站…

服务器漏洞防护措施有哪些?

随着互联网的普及和发展,服务器在各个领域的应用越来越广泛,同时也面临着越来越多的安全威胁。服务器漏洞一旦被攻击者利用,不仅可能导致数据泄露、系统崩溃等严重后果,还可能影响到企业的正常运营和声誉。因此,加强服…

jmeter简单压测kafka

前言 这也是一个笔记,就是计划用jmeter做性能测试,但是这里是只要将数据放到kafka的topic里,后面查看下游业务处理能力。 一、方案 因为只要实现数据放到kafka,参考了下博友的方案,可行。 二、方案验证 详细过程就不…

DevExpress WinForms Pivot Grid组件,一个类似Excel的数据透视表控件(二)

界面控件DevExpress WinForms的Pivot Grid组件是一个类似Excel的数据透视表控件,用于多维(OLAP)数据分析和跨选项卡报表。在上文中(点击这里回顾>>)我们介绍了DevExpress WinForms Pivot Grid组件的性能、分析服务、数据塑造能力等&…

23种策略模式之策略模式

23种策略模式之策略模式 文章目录 23种策略模式之策略模式前言优缺点使用场景角色定义UML模拟示例小结 前言 在软件开发中,设计模式是为了解决常见问题而提供的一套可重用的解决方案。策略模式(Strategy Pattern)是其中一种常见的设计模式&a…

Mac配置环境变量不生效

Mac配置环境变量不生效 Mac中的环境变量介绍 Mac系统的环境变量,加载顺序为: /etc/profile /etc/paths ~/.bash_profile ~/.bash_login ~/.profile ~/.bashrc 当然/etc/profile和/etc/paths是系统级别的,系统启动就会加载,后面…

Linux驱动入门 —— 利用引脚号操作GPIO进行LED点灯

目录 一、字符设备驱动程序框架 编写驱动程序的步骤: 对于 LED 驱动,我们想要什么样的接口? LED 驱动能支持多个板子的基础:分层思想 二、Linux驱动如何指向一个GPIO 直接通过寄存器来操作GPIO 利用引脚号操作GPIO IMX6UL…

基于自动化脚本批量上传依赖到nexus内网私服

前言 因为某些原因某些企业希望私服是不能连接外网的,所以需要某些开源依赖需要我们手动导入到nexus中,尽管nexus为我们提供了web页面。但是一个个手动导入显然是一个庞大的工程。 对此我们就不妨基于脚本的方式实现这一过程。 预期效果 笔者本地仓库…

【Java】网络编程-UDP回响服务器客户端简单代码编写

这一篇文章我们将讲述网络编程中UDP服务器客户端的编程代码 1、前置知识 UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。 UDP的特点有:无连接、尽最大努力交付、面向报文、没有拥塞控制 本文讲…

为什么FPGA是战略芯片?

FPGA(Field Programmable Gate Array)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物,它是作为一种半定制电路而出现的,既解决了定制电路的不足&…

提升数据采集技能:用 Axios 实现的 Twitter 视频下载器全面解析

引入 在当今数据驱动的时代,高效的数据采集是实现成功数据科学项目的关键。数据采集不仅涉及到数据的获取,还包括数据的清洗、转换、存储和分析等多个环节。Twitter作为全球最大的社交媒体平台之一,蕴含着丰富的信息和海量的多媒体内容&…

计算机网络:数据链路层(网桥)

带你速通计算机网络期末 目录 一、冲突域和广播域 二、网桥介绍 三、网桥分类—―透明网桥 四、网桥分类―—源路由网桥 五、多接口网桥―—以太网交换机 总结 一、冲突域和广播域 冲突域:在同一个冲突域中的每一个节点都能收到所有被发送的帧。简单的说就是同一时间内只…

C# WPF上位机开发(内嵌虚拟机的软件开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 学习过halcon的同学都知道,它不仅有很多的图像算子可以使用,而且调试很方便。每一步骤的调试结果,都可以看到对…

WWW 指南-万维网联盟(World Wide Web)

WWW - 万维网联盟 WWW通常称为网络。 web是一个世界各地的计算机网络。 电脑在Web上使用标准语言沟通。 万维网联盟(W3C)制定了Web标准 什么是WWW? WWW 代表 World Wide Web(万维网)万维网常常被称为 网络网络是世界各地的计算机网络网络中…

Spark分布式内存计算框架

目录 一、Spark简介 (一)定义 (二)Spark和MapReduce区别 (三)Spark历史 (四)Spark特点 二、Spark生态系统 三、Spark运行架构 (一)基本概念 &#x…

博客社区资讯APP源码/开源知识付费社区小程序源码/资源社区源码/独有付费阅读+兼容安卓苹果

源码简介: 博客社区资讯APP源码,它是开源知识付费小程序源码,作为资源社区源码,它具有独有付费阅读兼容安卓苹果。它是Typecho后端的。 知识付费社区RuleApp多内容发布,后端基于Typoche博客程序开发带完整安装文档 竟…