Hadoop之Avro介紹

原文地址: https://itweknow.cn/detail?id=70 ,歡迎大家訪問。

什么是Avro

Avro是一個獨立于編程語言的數(shù)據(jù)序列化系統(tǒng)。這個項目由Ddoug Cutting(Hadoop之父)創(chuàng)建,目標是解決Hadoop中Writable類型缺乏語言的可移植性的不足。Avro模式通常采用JSON來寫,數(shù)據(jù)則采用二進制格式編碼,也可采用基于JSON的數(shù)據(jù)編碼方式。

Avro的數(shù)據(jù)類型和模式

Avro定義了一些基本的數(shù)據(jù)類型,我們可以用他們來構(gòu)建應用特定的數(shù)據(jù)結(jié)構(gòu)。下面的表格我們列舉了Avro的基本類型。

類型 描述 模式示例
null 空值 "null"
boolean 二進制值 "boolean"
int 32位帶符號整數(shù) "int"
long 64位帶符號整數(shù) "long"
float 單精度(32位)浮點數(shù) "float"
double 雙精度(64位)浮點數(shù) "double"
bytes 8位無符號字節(jié)序列 "bytes"
string Unicode字符序列 "string"

還有一些復雜的類型如下表所示:

類型 描述 模式示例
array 一個排過序的對象集合。特定數(shù)組中的所有對象必須模式相同。 {"type": "array","items": "long"}
map 未排過序的鍵-值對。鍵必須是字符串,值可以是任何一種類型,但是某一個map內(nèi)的所有值必須模式相同。 {"type": "map", "values": "string"}
record 一個任意類型的命名字段集合。(相當于java中的自定義對象) {"type": "record", "name": "User", "doc":"A User Desc","fileds":[{"name":"nickname","type": "string"},{"name":"age","type":"int"}]}
enum 一個命名的值集合(枚舉) {"type":"enum","name":"ActionStatus","doc":"操作狀態(tài)","symbols":["SUCCESS","FAILED","ACTING"]}
fixed 一組固定數(shù)量的8位無符號字節(jié) {"type":"fixed","name":"Md5Hash","size":16}
union 模式的并集。并集可用JSON數(shù)組表示,其中每個元素為一個模式。并集表示的數(shù)據(jù)必須與其內(nèi)的某個模式相匹配 ["null","string",{"type":"map","values":"string"}]

Avro數(shù)據(jù)文件

前面也提到過設計Avro的目的就是解決Hadoop中Writable類型缺乏語言的可移植性的不足。Avro數(shù)據(jù)文件主要是面向跨語言使用而設計的,我們可以通過Java寫入文件,然后通過Python來讀取文件,這都是沒有問題的。數(shù)據(jù)文件的頭部包含一個Avro模式和一個同步標識(sync marker),然后緊接著是一系列包含序列化Avro對象的數(shù)據(jù)塊。數(shù)據(jù)塊通過sync marker分隔。
這里有兩個概念解釋一下:

  • Avro模式 - 其實就相當于對象的定義,在這里我們規(guī)定字段的類型以及描述等信息。
  • sync marker - 對與該文件來講是唯一的,存儲在文件頭部。

序列化和反序列化

上面也簡單的了解了一下Avro,下面我們通過兩段代碼來嘗試一下Avro的序列化和反序列化。

  • Avro模式定義,User.avsc
{
    "type": "record",
    "name": "User",
    "doc": "一個用戶",
    "fields": [
        {"name": "name", "type": "string"},
        {"name": "age", "type": "int"}
    ]
}
  • 序列化
@Test
public void write() throws IOException {
    Schema.Parser parser = new Schema.Parser();
    InputStream in = this.getClass().getResourceAsStream("User.avsc");
    Schema schema = parser.parse(in);
    GenericRecord record = new GenericData.Record(schema);
    record.put("name", "ganchaoyang");
    record.put("age", 23);

    File file = new File("result.avro");
    DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
    try(DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(writer)) {
        dataFileWriter.create(schema, file);
        dataFileWriter.append(record);
    }
}
  • 反序列化
@Test
public void read() throws IOException {
    File file = new File("result.avro");
    DatumReader<GenericRecord> reader = new GenericDatumReader<>();
    try (DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader)) {
        GenericRecord record;
        while (dataFileReader.hasNext()) {
            record = dataFileReader.next();
            Assert.assertEquals("ganchaoyang", record.get("name").toString());
            Assert.assertEquals(23, record.get("age"));
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容