日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Avro介绍[通俗易懂](Apache)

發(fā)布時間:2023/12/19 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 Avro介绍[通俗易懂](Apache) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Apache Avro是一個數(shù)據(jù)序列化系統(tǒng)。

Avro所提供的屬性:

1.豐富的數(shù)據(jù)結(jié)構(gòu)
2.使用快速的壓縮二進(jìn)制數(shù)據(jù)格式
3.提供容器文件用于持久化數(shù)據(jù)
4.遠(yuǎn)程過程調(diào)用RPC
5.簡單的動態(tài)語言結(jié)合功能,Avro 和動態(tài)語言結(jié)合后,讀寫數(shù)據(jù)文件和使用 RPC 協(xié)議都不需要生成代碼,而代碼生成作為一種可選的優(yōu)化只值得在靜態(tài)類型語言中實現(xiàn)。

Avro的Schema

Avro的Schema用JSON表示。Schema定義了簡單數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型。

基本類型

其中簡單數(shù)據(jù)類型有以下8種:

類型 含義
null 沒有值
boolean 布爾值
int 32位有符號整數(shù)
long 64位有符號整數(shù)
float 單精度(32位)的IEEE 754浮點數(shù)
double 雙精度(64位)的IEEE 754浮點數(shù)
bytes 8位無符號字節(jié)序列
string 字符串

基本類型沒有屬性,基本類型的名字也就是類型的名字,比如:

{"type": "string"}

Jetbrains全家桶1年46,售后保障穩(wěn)定

復(fù)雜類型

Avro提供了6種復(fù)雜類型。分別是Record,Enum,Array,Map,Union和Fixed。

Record

Record類型使用的類型名字是 “record”,還支持其它屬性的設(shè)置:

name:record類型的名字(必填)

namespace:命名空間(可選)

doc:這個類型的文檔說明(可選)

aliases:record類型的別名,是個字符串?dāng)?shù)組(可選)

fields:record類型中的字段,是個對象數(shù)組(必填)。每個字段需要以下屬性:

  1. name:字段名字(必填)
  2. doc:字段說明文檔(可選)
  3. type:一個schema的json對象或者一個類型名字(必填)
  4. default:默認(rèn)值(可選)
  5. order:排序(可選),只有3個值ascending(默認(rèn)),descending或ignore
  6. aliases:別名,字符串?dāng)?shù)組(可選)

一個Record類型例子,定義一個元素類型是Long的鏈表:

{
  "type": "record", 
  "name": "LongList",
  "aliases": ["LinkedLongs"],                      // old name for this
  "fields" : [
    {"name": "value", "type": "long"},             // each element has a long
    {"name": "next", "type": ["null", "LongList"]} // optional next element
  ]
}

Enum

枚舉類型的類型名字是”enum”,還支持其它屬性的設(shè)置:

name:枚舉類型的名字(必填)
namespace:命名空間(可選)
aliases:字符串?dāng)?shù)組,別名(可選)
doc:說明文檔(可選)
symbols:字符串?dāng)?shù)組,所有的枚舉值(必填),不允許重復(fù)數(shù)據(jù)。

一個枚舉類型的例子:

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

Array

數(shù)組類型的類型名字是”array”并且只支持一個屬性:

items:數(shù)組元素的schema

一個數(shù)組例子:

{"type": "array", "items": "string"}

Map

Map類型的類型名字是”map”并且只支持一個屬性:

values:map值的schema

Map的key必須是字符串。

一個Map例子:

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

Union

組合類型,表示各種類型的組合,使用數(shù)組進(jìn)行組合。比如[“null”, “string”]表示類型可以為null或者string。

組合類型的默認(rèn)值是看組合類型的第一個元素,因此如果一個組合類型包括null類型,那么null類型一般都會放在第一個位置,這樣子的話這個組合類型的默認(rèn)值就是null。

組合類型中不允許同一種類型的元素的個數(shù)不會超過1個,除了record,fixed和enum。比如組合類中有2個array類型或者2個map類型,這是不允許的。

組合類型不允許嵌套組合類型。

Fixed

混合類型的類型名字是fixed,支持以下屬性:

name:名字(必填)
namespace:命名空間(可選)
aliases:字符串?dāng)?shù)組,別名(可選)
size:一個整數(shù),表示每個值的字節(jié)數(shù)(必填)

比如16個字節(jié)數(shù)的fixed類型例子如下:

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

1個Avro例子

首先定義一個User的schema:

{
"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": "int"},
     {"name": "favorite_color", "type": "string"}
 ]
}

User有3個屬性,分別是name,favorite_number和favorite_color。

json文件內(nèi)容:

{"name":"format","favorite_number":1,"favorite_color":"red"}
{"name":"format2","favorite_number":2,"favorite_color":"black"}
{"name":"format3","favorite_number":666,"favorite_color":"blue"}

使用avro工具將json文件轉(zhuǎn)換成avro文件:

java -jar avro-tools-1.8.0.jar fromjson --schema-file user.avsc user.json > user.avro

可以設(shè)置壓縮格式:

java -jar avro-tools-1.8.0.jar fromjson --codec snappy --schema-file user.avsc user.json > user2.avro

將avro文件反轉(zhuǎn)換成json文件:

java -jar avro-tools-1.8.0.jar tojson user.avro
java -jar avro-tools-1.8.0.jar --pretty tojson user.avro

得到avro文件的meta:

java -jar avro-tools-1.8.0.jar getmeta user.avro

輸出:

avro.codec    null
avro.schema    {"type":"record","name":"User","namespace":"example.avro","fields":[{"name":"name","type":"string"},{"name":"favorite_number","type":"int"},{"name":"favorite_color","type":"string"}]}

得到avro文件的schema:

java -jar avro-tools-1.8.0.jar getschema user.avro

將文本文件轉(zhuǎn)換成avro文件:

java -jar avro-tools-1.8.0.jar fromtext user.txt usertxt.avro

Avro使用生成的代碼進(jìn)行序列化和反序列化

以上面一個例子的schema為例講解。

Avro可以根據(jù)schema自動生成對應(yīng)的類:

java -jar /path/to/avro-tools-1.8.0.jar compile schema user.avsc .

user.avsc的namespace為example.avro,name為User。最終在當(dāng)前目錄生成的example/avro目錄下有個User.java文件。

├── example
│   └── avro
│       └── User.java

使用Avro生成的代碼創(chuàng)建User:

User user1 = new User();
user1.setName("Format");
user1.setFavoriteColor("red");
user1.setFavoriteNumber(666);

User user2 = new User("Format2", 66, "blue");

User user3 = User.newBuilder()
                .setName("Format3")
                .setFavoriteNumber(6)
                .setFavoriteColor("black").build();

可以使用有參的構(gòu)造函數(shù)和無參的構(gòu)造函數(shù),也可以使用Builder構(gòu)造User。

序列化:

DatumWrite接口用來把java對象轉(zhuǎn)換成內(nèi)存中的序列化格式,SpecificDatumWriter用來生成類并且指定生成的類型。

最后使用DataFileWriter來進(jìn)行具體的序列化,create方法指定文件和schema信息,append方法用來寫數(shù)據(jù),最后寫完后close文件。

DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
        DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
dataFileWriter.create(user1.getSchema(), new File("users.avro"));
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.append(user3);
dataFileWriter.close();

反序列化:

反序列化跟序列化很像,相應(yīng)的Writer換成Reader。這里只創(chuàng)建一個User對象是為了性能優(yōu)化,每次都重用這個User對象,如果文件量很大,對象分配和垃圾收集處理的代價很昂貴。如果不考慮性能,可以使用 for (User user : dataFileReader) 循環(huán)遍歷對象

File file = new File("users.avro");
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = new DataFileReader<User>(file, userDatumReader);
User user = null;
while(dataFileReader.hasNext()) {
    user = dataFileReader.next(user);
    System.out.println(user);
}

打印出:

{"name": "Format", "favorite_number": 666, "favorite_color": "red"}
{"name": "Format2", "favorite_number": 66, "favorite_color": "blue"}
{"name": "Format3", "favorite_number": 6, "favorite_color": "black"}

Avro不使用生成的代碼進(jìn)行序列化和反序列化

雖然Avro為我們提供了根據(jù)schema自動生成類的方法,我們也可以自己創(chuàng)建類,不使用Avro的自動生成工具。

創(chuàng)建User:

首先使用Parser讀取schema信息并且創(chuàng)建Schema類:

Schema schema = new Schema.Parser().parse(new File("user.avsc"));

有了Schema之后可以創(chuàng)建record:

GenericRecord user1 = new GenericData.Record(schema);
user1.put("name", "Format");
user1.put("favorite_number", 666);
user1.put("favorite_color", "red");

GenericRecord user2 = new GenericData.Record(schema);
user2.put("name", "Format2");
user2.put("favorite_number", 66);
user2.put("favorite_color", "blue");

使用GenericRecord表示User,GenericRecord會根據(jù)schema驗證字段是否正確,如果put進(jìn)了不存在的字段 user1.put(“favorite_animal”, “cat”) ,那么運(yùn)行的時候會得到AvroRuntimeException異常。

序列化:

序列化跟生成的User類似,只不過schema是自己構(gòu)造的,不是User中拿的。

Schema schema = new Schema.Parser().parse(new File("user.avsc"));
GenericRecord user1 = new GenericData.Record(schema);
user1.put("name", "Format");
user1.put("favorite_number", 666);
user1.put("favorite_color", "red");

GenericRecord user2 = new GenericData.Record(schema);
user2.put("name", "Format2");
user2.put("favorite_number", 66);
user2.put("favorite_color", "blue");

DatumWriter<GenericRecord> datumWriter = new SpecificDatumWriter<GenericRecord>(schema);
DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
dataFileWriter.create(schema, new File("users2.avro"));
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.close();

反序列化:

反序列化跟生成的User類似,只不過schema是自己構(gòu)造的,不是User中拿的。

Schema schema = new Schema.Parser().parse(new File("user.avsc"));
File file = new File("users2.avro");
DatumReader<GenericRecord> datumReader = new SpecificDatumReader<GenericRecord>(schema);
DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, datumReader);
GenericRecord user = null;
while(dataFileReader.hasNext()) {
    user = dataFileReader.next(user);
    System.out.println(user);
}

打印出:

{"name": "Format", "favorite_number": 666, "favorite_color": "red"}
{"name": "Format2", "favorite_number": 66, "favorite_color": "blue"}

一些注意點

Avro解析json文件的時候,如果類型是Record并且里面有字段是union并且允許空值的話,需要進(jìn)行轉(zhuǎn)換。因為[“bytes”, “string”]和[“int”,”long”]這2個union類型在json中是有歧義的,第一個union在json中都會被轉(zhuǎn)換成string類型,第二個union在json中都會被轉(zhuǎn)換成數(shù)字類型。

所以如果json值的null的話,在avro提供的json中直接寫null,否則使用只有一個鍵值對的對象,鍵是類型,值的具體的值。

比如:

{
"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["int","null"]},
     {"name": "favorite_color", "type": ["string","null"]}
 ]
}

在要轉(zhuǎn)換成json文件的時候要寫成這樣:

{"name":"format","favorite_number":{"int":1},"favorite_color":{"string":"red"}}
{"name":"format2","favorite_number":null,"favorite_color":{"string":"black"}}
{"name":"format3","favorite_number":{"int":66},"favorite_color":null}

Spark讀取Avro文件

直接遍歷avro文件,得到GenericRecord進(jìn)行處理:

val conf = new SparkConf().setMaster("local").setAppName("AvroTest")

val sc = new SparkContext(conf)

val rdd = sc.hadoopFile[AvroWrapper[GenericRecord], NullWritable, AvroInputFormat[GenericRecord]](this.getClass.getResource("/").toString + "users.avro")

val nameRdd = rdd.map(s => s._1.datum().get("name").toString)

nameRdd.collect().foreach(println)

使用Avro需要注意的地方

筆者使用Avro的時候暫時遇到了下面2個坑。先記錄一下,以后遇到新的坑會更新這篇文章。

1.如果定義了unions類型的字段,而且unions中有null選項的schema,比如如下schema:

{
"namespace": "example.avro",
 "type": "record",
 "name": "User2",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["null","int"]},
     {"name": "favorite_color", "type": ["null","string"]}
 ]
}

這樣的schema,如果不使用Avro自動生成的model代碼進(jìn)行insert,并且insert中的model數(shù)據(jù)有null數(shù)據(jù)的話。然后用spark讀avro文件的話,會報org.apache.avro.AvroTypeException: Found null, expecting int … 這樣的錯誤。

這一點很奇怪,但是使用Avro生成的Model進(jìn)行insert的話,sprak讀取就沒有任何問題。 很困惑。

2.如果使用了Map類型的字段,avro生成的model中的Map的Key默認(rèn)類型為CharSequence。這種model我們insert數(shù)據(jù)的話,用String是沒有問題的。但是spark讀取之后要根據(jù)Key拿這個Map數(shù)據(jù)的時候,永遠(yuǎn)得到的是null。

stackoverflow上有一個頁面說到了這個問題。http://stackoverflow.com/questions/19728853/apache-avro-map-uses-charsequence-as-key

需要在map類型的字段里加上”avro.java.string”: “String”這個選項, 然后compile的時候使用-string參數(shù)即可。

比如以下這個schema:

{
"namespace": "example.avro",
 "type": "record",
 "name": "User3",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["null","int"]},
     {"name": "favorite_color", "type": ["null","string"]},
     {"name": "scores", "type": ["null", {"type": "map", "values": "string", "avro.java.string": "String"}]}
 ]
}

總結(jié)

以上是生活随笔為你收集整理的Avro介绍[通俗易懂](Apache)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品91一区二区 | 色婷婷av一区二区 | 五月综合色婷婷 | 男人日女人的网站 | 久久久久国产视频 | 中文字幕+乱码+中文乱码www | 无套内谢少妇露脸 | 欧美在线视频不卡 | 亚洲二级片 | 伊人久艹| 日韩区在线| 中文字幕欧美人妻精品 | 小泽玛利亚一区二区三区视频 | 国产丝袜在线 | 成人精品水蜜桃 | 播放黄色一级片 | 久久久免费高清视频 | 俺去久久 | 四虎影视www在线播放 | 蜜桃成人免费视频 | 免费av电影网址 | 91av在 | 丁香花高清在线 | 日韩乱码人妻无码中文字幕久久 | 午夜不卡av | 污视频网站免费 | 精品免费一区二区三区 | 九九热在线观看视频 | 国产精品1024 | 久久综合激的五月天 | 国产精品视频在 | www.色网站| 亚洲奶水xxxx哺乳期 | 免费在线国产 | 香蕉久久久久久久av网站 | 欧美精品一级二级 | 一区二区视频在线播放 | 日本三级大全 | 国产精品欧美一区喷水 | 久草免费在线视频 | 亚洲精品乱码久久 | 在线观看的av网站 | 亚洲色图丝袜美腿 | 网站久久久| av毛片在线免费观看 | 久久久久久亚洲 | 国产乡下妇女做爰毛片 | 超碰免费在 | 在线va视频 | 插插插日日日 | 亚洲天堂毛片 | 丰腴饱满的极品熟妇 | 韩国av三级 | 亚洲第一国产 | 蜜臀av在线观看 | 国产精品影院在线观看 | 高潮喷水一区二区三区 | 免费在线观看毛片 | 国产98在线 | 亚洲成av人影院 | 国产一级二级在线 | 亚洲系列在线观看 | 日韩第1页 | 自拍偷拍第八页 | 激情视频一区二区 | 国产在线久| 欧美韩日国产 | 理论片第一页 | 欧美高h | 亚洲国产日韩在线 | 91久久一区二区 | 成人在线观看国产 | 好吊妞在线 | 日韩av在线中文字幕 | 亚洲喷潮 | 午夜精品久久久久久久99老熟妇 | 国产精品1区2区3区4区 | 亚州男人天堂 | 国产又大又粗又爽 | 无码日韩人妻精品久久蜜桃 | 国产美女激情视频 | 无遮挡在线观看 | 欧美一级黄色片网站 | 亚洲第一大网站 | 国产性爱精品视频 | 成人动漫在线观看 | 一级毛片基地 | 国产黄频在线观看 | 欧美日韩毛片 | 日韩av在线播 | 欧美99久久精品乱码影视 | 婷婷五月综合激情 | 精品+无码+在线观看 | 亚洲免费视频播放 | 亚洲国产图片 | 欧美日韩视频网站 | 欧美性受xxx | 日本色www | 亚洲欧美动漫 |