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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

AVRO讲解

發(fā)布時間:2024/1/1 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AVRO讲解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、引言

1、?簡介

Avro是Hadoop中的一個子項目,也是Apache中一個獨立的項目,Avro是一個基于二進(jìn)制數(shù)據(jù)傳輸高性能的中間件。在Hadoop的其他項目中例如HBase(Ref)和Hive(Ref)的Client端與服務(wù)端的數(shù)據(jù)傳輸也采用了這個工具。Avro是一個數(shù)據(jù)序列化的系統(tǒng)。Avro 可以將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)化成便于存儲或傳輸?shù)母袷健vro設(shè)計之初就用來支持?jǐn)?shù)據(jù)密集型應(yīng)用,適合于遠(yuǎn)程或本地大規(guī)模數(shù)據(jù)的存儲和交換。

2、?特點

? 豐富的數(shù)據(jù)結(jié)構(gòu)類型;

? 快速可壓縮的二進(jìn)制數(shù)據(jù)形式,對數(shù)據(jù)二進(jìn)制序列化后可以節(jié)約數(shù)據(jù)存儲空間和網(wǎng)絡(luò)傳輸帶寬;

? 存儲持久數(shù)據(jù)的文件容器;

? 可以實現(xiàn)遠(yuǎn)程過程調(diào)用RPC;

? 簡單的動態(tài)語言結(jié)合功能。

avro支持跨編程語言實現(xiàn)(C, C++, C#,Java, Python, Ruby, PHP),類似于Thrift,但是avro的顯著特征是:avro依賴于模式,動態(tài)加載相關(guān)數(shù)據(jù)的模式,Avro數(shù)據(jù)的讀寫操作很頻繁,而這些操作使用的都是模式,這樣就減少寫入每個數(shù)據(jù)文件的開銷,使得序列化快速而又輕巧。這種數(shù)據(jù)及其模式的自我描述方便了動態(tài)腳本語言的使用。當(dāng)Avro數(shù)據(jù)存儲到文件中時,它的模式也隨之存儲,這樣任何程序都可以對文件進(jìn)行處理。如果讀取數(shù)據(jù)時使用的模式與寫入數(shù)據(jù)時使用的模式不同,也很容易解決,因為讀取和寫入的模式都是已知的。

New schema

Writer

Reader

Action

Added field

Old

New

The reader uses the default value of the new field, since it is not written by the writer.

?

New

Old

The reader does not know about the new field written by the writer, so it is ignored

(projection).

Removed field

Old

New

The reader ignores the removed field (projection).

?

New

Old

The removed field is not written by the writer. If the old schema had a default defined

for the field, the reader uses this; otherwise, it gets an error. In this case, it is best to

update the reader’s schema, either at the same time as or before the writer’s.

Avro和動態(tài)語言結(jié)合后,讀/寫數(shù)據(jù)文件和使用RPC協(xié)議都不需要生成代碼,而代碼生成作為一種可選的優(yōu)化只需要在靜態(tài)類型語言中實現(xiàn)。

Avro依賴于模式(Schema)。通過模式定義各種數(shù)據(jù)結(jié)構(gòu),只有確定了模式才能對數(shù)據(jù)進(jìn)行解釋,所以在數(shù)據(jù)的序列化和反序列化之前,必須先確定模式的結(jié)構(gòu)。正是模式的引入,使得數(shù)據(jù)具有了自描述的功能,同時能夠?qū)崿F(xiàn)動態(tài)加載,另外與其他的數(shù)據(jù)序列化系統(tǒng)如Thrift相比,數(shù)據(jù)之間不存在其他的任何標(biāo)識,有利于提高數(shù)據(jù)處理的效率。????

二、技術(shù)要領(lǐng)

1、?類型

數(shù)據(jù)類型標(biāo)準(zhǔn)化的意義:一方面使不同系統(tǒng)對相同的數(shù)據(jù)能夠正確解析,另一方面,數(shù)據(jù)類型的標(biāo)準(zhǔn)定義有利于數(shù)據(jù)序列化/反序列化。

簡單的數(shù)據(jù)類型:Avro定義了幾種簡單數(shù)據(jù)類型,下表是其簡單說明:

類型

說明

null

no value

boolean

a binary value

int

32-bit signed integer

long

64-bit signed integer

float

single precision (32-bit) IEEE 754 floating-point number

double

double precision (64-bit) IEEE 754 floating-point number

bytes

sequence of 8-bit unsigned bytes

string

unicode character sequence

簡單數(shù)據(jù)類型由類型名稱定義,不包含屬性信息,例如字符串定義如下:

{"type": "string"}

復(fù)雜數(shù)據(jù)類型:Avro定義了六種復(fù)雜數(shù)據(jù)類型,每一種復(fù)雜數(shù)據(jù)類型都具有獨特的屬性,下表就每一種復(fù)雜數(shù)據(jù)類型進(jìn)行說明。

類型

屬性

說明

Records

type name

record

name

a JSON string providing the name of the record (required).

namespace

a JSON string that qualifies the name(optional).

doc

a JSON string providing documentation to the user of this schema (optional).

aliases

a JSON array of strings, providing alternate names for this record (optional).

fields

a JSON array, listing fields (required).

??????????? name

a JSON string.

??????????? type

a schema/a string of defined record.

??????????? default

a default value for field when lack.

??????????? order

ordering of this field.

Enums

type name

enum

?

name

a JSON string providing the name of the enum (required).

namespace

a JSON string that qualifies the name.

doc

a JSON string providing documentation to the user of this schema (optional).

aliases

a JSON array of strings, providing alternate names for this enum (optional)

symbols

a JSON array, listing symbols, as JSON strings (required). All symbols in an enum must be unique.

Arrays

type name

array

?

items

the schema of the array’s items.

Maps

type name

map

?

values

the schema of the map’s values.

Fixed

type name

fixed

?

name

a string naming this fixed (required).

?

namespace

a string that qualifies the name.

?

aliases

a JSON array of strings, providing alternate names for this enum (optional).

?

size

an integer, specifying the number of bytes per value (required).

Unions

?

a JSON arrays

每一種復(fù)雜數(shù)據(jù)類型都含有各自的一些屬性,其中部分屬性是必需的,部分是可選的。

這里需要說明Record類型中field屬性的默認(rèn)值,當(dāng)Record Schema實例數(shù)據(jù)中某個field屬性沒有提供實例數(shù)據(jù)時,則由默認(rèn)值提供,具體值見下表。Union的field默認(rèn)值由Union定義中的第一個Schema決定。

avro type

json type

example

null

null

null

boolean

boolean

true

int,long

integer

1

float,double

number

1.1

bytes

string

"\u00FF"

string

string

"foo"

record

object

{"a": 1}

enum

string

"FOO"

array

array

[1]

map

object

{"a": 1}

fixed

string

"\u00ff"

2、?序列化/反序列化

Avro指定兩種數(shù)據(jù)序列化編碼方式:binary encoding 和Json encoding。使用二進(jìn)制編碼會高效序列化,并且序列化后得到的結(jié)果會比較小;而JSON一般用于調(diào)試系統(tǒng)或是基于WEB的應(yīng)用。

binary encoding規(guī)則如下:

1、? 簡單數(shù)據(jù)類型

Type

Encoding

Example

null

Zero bytes

Null

boolean

A single byte

{true:1, false:0}

int/long

variable-length zig-zag coding

?

float

4 bytes

Java's floatToIntBits

double

8 bytes

Java's doubleToLongBits

bytes

a long followed by that many bytes of data

?

string

a long followed by that many bytes of UTF-8 encoded character data

“foo”:{3,f,o,o}

06 66 6f 6f

2、? 復(fù)雜數(shù)據(jù)類型

Type

encoding

Records

encoded just the concatenation of the encodings of its?fields

Enums

a int representing the zero-based?position?of the symbol in the schema

Arrays

encoded as series of blocks. A block with count 0 indicates the end of the array. block:{long,items}

Maps

encoded as series of blocks. A block with count 0 indicates the end of the map. block:{long,key/value pairs}.

Unions

encoded by first writing a long value indicating the zero-based position within the union of the schema of its value. The value is then encoded per the indicated schema within the union.

fixed

encoded using number of bytes declared in the schema

實例:

?records

{

"type":"record",

"name":"test",

"fields" : [

{"name": "a","type": "long"},

{"name": "b","type": "string"}

]

}

假設(shè):a=27b=”foo” (encoding:36(27), 06(3), 66("f"), 6f("o"))

binary encoding:3606 66 6f 6f

?enums

{"type": "enum","name": "Foo", "symbols": ["A","B", "C", "D"] }

“D”(encoding: 06(3))

binary encoding: 06

?arrays

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

設(shè):{3, 27 } (encoding:04(2), 06(3), 36(27) )

binary encoding:0406 36 00

?maps

設(shè):{("a":1), ("b":2) } (encoding:61(“a”), 62(“b”), 02(1), 04(2))

binary encoding:0261 02 02 62 04

?unions

["string","null"]

設(shè):(1)null; (2) “a”

binary encoding:

(1) 02;說明:02代表null在union定義中的位置1;

(2) 00 02 61;說明:00為string在union定義的位置,02 61為”a”的編碼。

?

圖1表示的是Avro本地序列化和反序列化的實例,它將用戶定義的模式和具體的數(shù)據(jù)編碼成二進(jìn)制序列存儲在對象容器文件中,例如用戶定義了包含學(xué)號、姓名、院系和電話的學(xué)生模式,而Avro對其進(jìn)行編碼后存儲在student.db文件中,其中存儲數(shù)據(jù)的模式放在文件頭的元數(shù)據(jù)中,這樣讀取的模式即使與寫入的模式不同,也可以迅速地讀出數(shù)據(jù)。假如另一個程序需要獲取學(xué)生的姓名和電話,只需要定義包含姓名和電話的學(xué)生模式,然后用此模式去讀取容器文件中的數(shù)據(jù)即可。

????????????????????????????? ??????????????????????????? 圖表 1

?

3、?模式Schema

Schema通過JSON對象表示。Schema定義了簡單數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型,其中復(fù)雜數(shù)據(jù)類型包含不同屬性。通過各種數(shù)據(jù)類型用戶可以自定義豐富的數(shù)據(jù)結(jié)構(gòu)。

Schema由下列JSON對象之一定義:

1. JSON字符串:命名

2. JSON對象:{“type”: “typeName” …attributes…}

3. JSON數(shù)組:Avro中Union的定義

舉例:

{"namespace": "example.avro",

?"type":"record",

?"name":"User",

?"fields": [

???? {"name":"name", "type": "string"},

???? {"name":"favorite_number",?"type": ["int", "null"]},

???? {"name":"favorite_color", "type": ["string","null"]}

?]

}

4、?排序

Avro為數(shù)據(jù)定義了一個標(biāo)準(zhǔn)的排列順序。比較在很多時候是經(jīng)常被使用到的對象之間的操作,標(biāo)準(zhǔn)定義可以進(jìn)行方便有效的比較和排序。同時標(biāo)準(zhǔn)的定義可以方便對Avro的二進(jìn)制編碼數(shù)據(jù)直接進(jìn)行排序而不需要反序列化。

只有當(dāng)數(shù)據(jù)項包含相同的Schema的時候,數(shù)據(jù)之間的比較才有意義。數(shù)據(jù)的比較按照Schema深度優(yōu)先,從左至右的順序遞歸的進(jìn)行。找到第一個不匹配即可終止比較。

兩個擁有相同的模式的項的比較按照以下規(guī)則進(jìn)行:

?????? null:總是相等。

int,long,float:按照數(shù)值大小比較。

boolean:false在true之前。

string:按照字典序進(jìn)行比較。

bytes,fixed:按照byte的字典序進(jìn)行比較。

array:按照元素的字典序進(jìn)行比較。

enum:按照符號在枚舉中的位置比較。

record:按照域的字典序排序,如果指定了以下屬性:

“ascending”,域值的順序不變。

“descending”,域值的順序顛倒。

“ignore”,排序的時候忽略域值。

map:不可進(jìn)行比較。

?

5、?對象容器文件

Avro定義了一個簡單的對象容器文件格式。一個文件對應(yīng)一個模式,所有存儲在文件中的對象都是根據(jù)模式寫入的。對象按照塊進(jìn)行存儲,塊可以采用壓縮的方式存儲。為了在進(jìn)行mapreduce處理的時候有效的切分文件,在塊之間采用了同步記號。一個文件可以包含任意用戶定義的元數(shù)據(jù)。

一個文件由兩部分組成:文件頭和一個或者多個文件數(shù)據(jù)塊。

文件頭:

?四個字節(jié),ASCII‘O’,‘b’,‘j’,1。

?文件元數(shù)據(jù),用于描述Schema。

?16字節(jié)的文件同步記號。

?其中,文件元數(shù)據(jù)的格式為:

???????????????????????i.?????????????值為-1的長整型,表明這是一個元數(shù)據(jù)塊。

?????????????????????ii.?????????????標(biāo)識塊長度的長整型。

???????????????????iii.?????????????標(biāo)識塊中key/value對數(shù)目的長整型。

????????????????????iv.?????????????每一個key/value對的string key和bytesvalue。

??????????????????????v.?????????????標(biāo)識塊中字節(jié)總數(shù)的4字節(jié)長的整數(shù)。

文件數(shù)據(jù)塊:

數(shù)據(jù)是以塊結(jié)構(gòu)進(jìn)行組織的,一個文件可以包含一個或者多個文件數(shù)據(jù)塊。

?表示文件中塊中對象數(shù)目的長整型。

?表示塊中數(shù)據(jù)序列化后的字節(jié)數(shù)長度的長整型。

?序列化的對象。

?16字節(jié)的文件同步記號。

當(dāng)數(shù)據(jù)塊的長度為0時即為文件數(shù)據(jù)塊的最后一個數(shù)據(jù),此后的所有數(shù)據(jù)被自動忽略。

下圖示對象容器文件的結(jié)構(gòu)分解及說明:

?

一個存儲文件由兩部分組成:頭信息(Header)和數(shù)據(jù)塊(Data Block)。而頭信息又由三部分構(gòu)成:四個字節(jié)的前綴,文件Meta-data信息和隨機(jī)生成的16字節(jié)同步標(biāo)記符。Avro目前支持的Meta-data有兩種:schema和codec。

codec表示對后面的文件數(shù)據(jù)塊(File Data Block)采用何種壓縮方式。Avro的實現(xiàn)都需要支持下面兩種壓縮方式:null(不壓縮)和deflate(使用Deflate算法壓縮數(shù)據(jù)塊)。除了文檔中認(rèn)定的兩種Meta-data,用戶還可以自定義適用于自己的Meta-data。這里用long型來表示有多少個Meta-data數(shù)據(jù)對,也是讓用戶在實際應(yīng)用中可以定義足夠的Meta-data信息。對于每對Meta-data信息,都有一個string型的key(需要以“avro.” 為前綴)和二進(jìn)制編碼后的value。對于文件中頭信息之后的每個數(shù)據(jù)塊,有這樣的結(jié)構(gòu):一個long值記錄當(dāng)前塊有多少個對象,一個long值用于記錄當(dāng)前塊經(jīng)過壓縮后的字節(jié)數(shù),真正的序列化對象和16字節(jié)長度的同步標(biāo)記符。由于對象可以組織成不同的塊,使用時就可以不經(jīng)過反序列化而對某個數(shù)據(jù)塊進(jìn)行操作。還可以由數(shù)據(jù)塊數(shù),對象數(shù)和同步標(biāo)記符來定位損壞的塊以確保數(shù)據(jù)完整性。

三、RPC實現(xiàn)

當(dāng)在RPC中使用Avro時,服務(wù)器和客戶端可以在握手連接時交換模式。服務(wù)器和客戶端有彼此全部的模式,因此相同命名字段、缺失字段和多余字段等信息之間通信中需要處理的一致性問題就可以容易解決。如圖2所示,協(xié)議中定義了用于傳輸?shù)南?#xff0c;消息使用框架后放入緩沖區(qū)中進(jìn)行傳輸,由于傳輸?shù)某跏季徒粨Q了各自的協(xié)議定義,因此即使傳輸雙方使用的協(xié)議不同所傳輸?shù)臄?shù)據(jù)也能夠正確解析。

圖表 2

Avro作為RPC框架來使用。客戶端希望同服務(wù)器端交互時,就需要交換雙方通信的協(xié)議,它類似于模式,需要雙方來定義,在Avro中被稱為消息(Message)。通信雙方都必須保持這種協(xié)議,以便于解析從對方發(fā)送過來的數(shù)據(jù),這也就是傳說中的握手階段。?

消息從客戶端發(fā)送到服務(wù)器端需要經(jīng)過傳輸層(Transport Layer),它發(fā)送消息并接收服務(wù)器端的響應(yīng)。到達(dá)傳輸層的數(shù)據(jù)就是二進(jìn)制數(shù)據(jù)。通常以HTTP作為傳輸模型,數(shù)據(jù)以POST方式發(fā)送到對方去。在 Avro中,它的消息被封裝成為一組緩沖區(qū)(Buffer),類似于下圖的模型:

如上圖,每個緩沖區(qū)以四個字節(jié)開頭,中間是多個字節(jié)的緩沖數(shù)據(jù),最后以一個空緩沖區(qū)結(jié)尾。這種機(jī)制的好處在于,發(fā)送端在發(fā)送數(shù)據(jù)時可以很方便地組裝不同數(shù)據(jù)源的數(shù)據(jù),接收方也可以將數(shù)據(jù)存入不同的存儲區(qū)。還有,當(dāng)往緩沖區(qū)中寫數(shù)據(jù)時,大對象可以獨占一個緩沖區(qū),而不是與其它小對象混合存放,便于接收方方便地讀取大對象。

對象容器文件是Avro的數(shù)據(jù)存儲的具體實現(xiàn),數(shù)據(jù)交換則由RPC服務(wù)提供,與對象容器文件類似,數(shù)據(jù)交換也完全依賴Schema,所以與Hadoop目前的RPC不同,Avro在數(shù)據(jù)交換之前需要通過握手過程先交換Schema。

1、 握手過程

握手的過程是確保Server和Client獲得對方的Schema定義,從而使Server能夠正確反序列化請求信息,Client能夠正確反序列化響應(yīng)信息。一般的,Server/Client會緩存最近使用到的一些協(xié)議格式,所以,大多數(shù)情況下,握手過程不需要交換整個Schema文本。

所有的RPC請求和響應(yīng)處理都建立在已經(jīng)完成握手的基礎(chǔ)上。對于無狀態(tài)的連接,所有的請求響應(yīng)之前都附有一次握手過程;對于有狀態(tài)的連接,一次握手完成,整個連接的生命期內(nèi)都有效。

具體過程:

Client發(fā)起HandshakeRequest,其中含有Client本身SchemaHash值和對應(yīng)Server端的Schema Hash值(clientHash!=null,clientProtocol=null, serverHash!=null)。如果本地緩存有serverHash值則直接填充,如果沒有則通過猜測填充。

Server用如下之一HandshakeResponse響應(yīng)Client請求:

(match=BOTH, serverProtocol=null,serverHash=null):當(dāng)Client發(fā)送正確的serverHash值且Server緩存相應(yīng)的clientHash。握手過程完成,之后的數(shù)據(jù)交換都遵守本次握手結(jié)果。

(match=CLIENT, serverProtocol!=null,serverHash!=null):當(dāng)Server緩存有Client的Schema,但是Client請求中ServerHash值不正確。此時Server發(fā)送Server端的Schema數(shù)據(jù)和相應(yīng)的Hash值,此次握手完成,之后的數(shù)據(jù)交換都遵守本次握手結(jié)果。

(match=NONE):當(dāng)Client發(fā)送的ServerHash不正確且Server端沒有Client Schema的緩存。這種情況下Client需要重新提交請求信息 (clientHash!=null,clientProtocol!=null, serverHash!=null),Server響應(yīng) (match=BOTH, serverProtocol=null,serverHash=null),此次握手過程完成,之后的數(shù)據(jù)交換都遵守本次握手結(jié)果。

握手過程使用的Schema結(jié)構(gòu)如下示。

{

"type":"record",

"name":"HandshakeRequest","namespace":"org.apache.avro.ipc",

"fields":[

{"name":"clientHash", "type": {"type": "fixed","name": "MD5", "size": 16}},

{"name":"clientProtocol", "type": ["null","string"]},

{"name":"serverHash", "type": "MD5"},

{"name":"meta", "type": ["null", {"type":"map", "values": "bytes"}]}

]

}

{

"type":"record",

"name":"HandshakeResponse", "namespace":"org.apache.avro.ipc",

"fields":[

{"name":"match","type": {"type": "enum","name": "HandshakeMatch",

"symbols":["BOTH", "CLIENT", "NONE"]}},

{"name":"serverProtocol", "type": ["null","string"]},

{"name":"serverHash","type": ["null", {"type":"fixed", "name": "MD5", "size": 16}]},

{"name":"meta","type": ["null", {"type":"map", "values": "bytes"}]}

]

}?

2、?消息幀格式

消息從客戶端發(fā)送到服務(wù)器端需要經(jīng)過傳輸層,它發(fā)送請求并接收服務(wù)器端的響應(yīng)。到達(dá)傳輸層的數(shù)據(jù)就是二進(jìn)制數(shù)據(jù)。通常以HTTP作為傳輸模型,數(shù)據(jù)以POST方式發(fā)送到對方去。在 Avro中消息首先分幀后被封裝成為一組緩沖區(qū)(Buffer)。

數(shù)據(jù)幀的格式如下:

?一系列Buffer:

1、4字節(jié)的Buffer長度

2、Buffer字節(jié)數(shù)據(jù)

?長度為0的Buffer結(jié)束數(shù)據(jù)幀?

3、?Call格式

一個調(diào)用由請求消息、結(jié)果響應(yīng)消息或者錯誤消息組成。請求和響應(yīng)包含可擴(kuò)展的元數(shù)據(jù),兩種消息都按照之前提出的方法分幀。

調(diào)用的請求格式為:

? 請求元數(shù)據(jù),一個類型值的映射。

? 消息名,一個Avro字符串。

? 消息參數(shù)。參數(shù)根據(jù)消息的請求定義序列化。

調(diào)用的響應(yīng)格式為:

? 響應(yīng)的元數(shù)據(jù),一個類型值的映射。

? 一字節(jié)的錯誤標(biāo)志位。

? 如果錯誤標(biāo)志為false,響應(yīng)消息,根據(jù)響應(yīng)的模式序列化。

如果錯誤標(biāo)志位true,錯誤消息,根據(jù)消息的錯誤聯(lián)合模式序列化。?

轉(zhuǎn)載于:https://www.cnblogs.com/livebetter/p/9480632.html

總結(jié)

以上是生活随笔為你收集整理的AVRO讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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