Avro 是 Hadoop 的一個子項目,由 Hadoop 的創始人 Doug Cutting 領頭開發,
當前最新版本為 1.7.0。Avro 是一個資料序列化(Data Serialization)系統,設計用於 支援大批資料交換的應用。它的主要特點為:支援二進位序列化方式,可以便捷、
快速地處理大量資料;支援動態語言(Dynamic Language),使動態語言(如:Java, C#) 可以更方便地處理序列化資料。
當前市場上有很多類似的序列化系統,如 Google 的 Protocol Buffers, Facebook 的 Thrift。這些序列化系統運行良好,完全可以滿足資料序列化應用的需求。因此 Avro 的開發,使許多人產生疑問:為何要重複開發一個全新資料序列化的系統?
Doug Cutting 撰文解釋道:Hadoop 現存的 RPC 系統遇到一些問題,如性能瓶頸(當 前採用 IPC 系統,它使用 Java 自帶的 DataOutputStream 和 DataInputStream)、伺服 器端和用戶端必須運行相同版本的 Hadoop、只能使用 Java 開發等問題。且現存的 序列化系統自身也存在問題;以 Protocol Buffers 為例,它需要使用者先定義資料 結構,然後根據這個資料結構生成代碼,再組裝資料。如果需要操作多個資料來 源的資料集,那麼需要定義多套資料結構並重複執行多次上面的流程,如此一來 就不能對任意資料集做統一處理。其次,對於 Hadoop 中 Hive 和 Pig 這樣的腳本 系統來說,使用代碼生成是不合理的。並且,Protocol Buffers 在序列化時考慮到資 料定義與資料可能不完全匹配,允許在資料中添加註解,這會讓資料變得龐大並 拖慢處理速度。而其它序列化系統也存在如 Protocol Buffers 類似的問題。所以為 了 Hadoop 未來的穩定性考慮,Doug Cutting 主導開發一套全新的序列化系統,也 就是 Avro。Avro 於 2009 年加入 Hadoop 專案家族中。
以上透過與 Protocol Buffers 的對比,大致了解 Avro 被設計出來的原因及其試 圖改善的部分;以下則著重於 Avro 設計細節。
Avro 依賴 Schema 來實現資料結構定義。Schema 定義每個 datum (Avro 支援的 資料型態) 物件結構可以包含哪些屬性,因此可以根據 Schema 來產生任意多個
‧
都需要 Schema 與資料同時存在。Avro 資料以 Schema 來決定如何讀、寫(Apache, 2012),且寫入的資料不需要再加入其它標識,使序列化時速度快且結果內容長度 也相對較小,解決上述其他序列化系統序列化速度慢的問題。
Avro 的 Schema 主要由 JSON 物件表示,包含一些特定的屬性,用以描述某種 資料類型(Type)的不同形式。Avro 支援八種基本類型(Primitive Type)和六種複雜類 型(Complex Type)。
Primitive Type:
[1] Null: no value
[2] Boolean: a binary value [3] Int:32-bit signed integer [4] Long:64-bit signed integer
[5] Float:single precision (32-bit) IEEE 754 floating-point number [6] Double:double precision (64-bit) IEEE 754 floating-point number [7] Bytes:sequence of 8-bit unsigned bytes
[8] String:unicode character sequence
Complex Type:
[1] Records:紀錄,支援五種屬性。
A. Name:提供 Record 之名稱。
B. Namespace:用以識別名稱的域名。
C. Aliases:Name 的別名,為一陣列。
D. Doc:其餘資訊。
E. Fields:為一陣列型態,儲存多個 Field,每個 Field 可包覆一 Avro 複雜型態。
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
29
[2] Enums:列舉,提供 Name、Namespace、Aliases、Doc 及 Symbol 屬性。
Symbol 為一 JSON 物件陣列,儲存多個常數。
[3] Arrays:陣列,提供 Items 屬性放置陣列內的元素。元素可以是 Avro 之複 雜型態。
[4] Maps:地圖,提供一組 Key Value 的 Collection,Key 的資料型態必須為 String,Value 可以是 Avro 之複雜型態,使用 Values 作為其參數。
[5] Unions:提供 Fields 中型態之選擇,使 Field 可包含的型態不只一種,也 可為 null。
[6] Fixed:用以限制型態內的長度,提供 Name、Alias 兩種參數。另提供 Size 作為 bytes 數的限制參數。
‧
大部分的傳統關聯式資料庫(Relational Database, RDB)皆以 Entity-Relationship Model(ERM)設計 Table 的概念模型,因此本研究將從 ERM 的觀點來說明關聯式資 料庫(RDB)暨欄導向資料庫(Column-oriented database, CDB)的轉換機制。ERM 實體 之間存在三種關係,分別為一對一(1-1)關係、一對多(1-m)關係、及多對多(m-n)關 係。假設一個實體 A 跟實體 B 發生關係,實體 B 又與實體 C 發生關係,這樣的一 個關係鏈,我們稱之為實體 A 與實體 C 擁有遞迴關係(Recursive Relation, R-R)。除 此之外,我們也定義兩實體間的 R-R 距離(R-R Length)為中間的實體數加 1。以上
ERM 中,一個實體代表一個關聯 Table。一個關聯 Table 包含一個主鍵(Primary Key)以及數個非主鍵的屬性(Field);主鍵可能是由數個 Field 組成。在欄導向資料 庫中,一個 CF 包含了多個擁有相同特性的 CQ,每個 CQ 在 CF 中都是唯一的。
在關聯 Table 中,一個主鍵的值識別了一個特定的列(Row)。同樣的,在欄導向資 料庫中,一個 RK 也識別了 HBase 中一張 Table 的特定列。因此,關聯式資料表的
‧
Table,我們將該主鍵列中的每個 Field 中的值以「:」作為區隔符號合併為單一的 值。轉換方法如下所述: where are called primary key fields.o Assumes that { } , be the set of primary key fields, constructed. The construction of includes two steps, the first step is to define the row key for and the second step is to define the column family for , which are described as follows.
o Step 1: For each primary key { } in , take
‧
圖 10. 實體關係轉換示意圖(Entity Relationship Translation)
圖 10 中,創建了與實體 A 對應的 Htable-HA,HA 包含一個名為 A_INFO(使 fields where are called primary key fields.
o Assumes that { } , be the set of primary key fields, fields where are called primary key fields.
o A set of non-primary key fields { } in , where
‧
construction for includes two steps, the first step is to define the row key for and the second step is to define the column family for , which are described as follows.o Step 1: For each primary key { } in , take
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
34
第二段 一對一關係轉換
除了上一段所闡述的實體關係轉換之外,實體間也存在著一對一的關係,因 此本段將針對一對一的關係轉換來做探討。
圖 11. 一對一關係轉換示意圖
一對一關係的兩個實體使用 Foriegn Key(FK)紀錄兩實體之間的關係。圖 11 中,
A table 使用 Bid 作為 FK 紀錄 A 與 B 之間的關係。兩個擁有一對一關係的實體在 關聯式資料庫中,會使用 Full outer join 儲存在一張 table 中,也就是使用其中一個 實體的主鍵來當作該 table 的主鍵。因此,轉換規則就變得相當簡單,只要把由 full outer join 產生的 table 做實體轉換至一張 HTable。是否要對兩邊做 Full outer join 則依照使用者的需求。如圖 10 所示,將 A 與 B 做 full outer join 然後將其產生之 table 做實體關係轉換即可。一對一的關係又可以分為 1-0 以及 1-1,如果為 1-0 則以 1 方為主鍵;如果是 1-1 則使用者可以依照使用者需求選擇任一邊做為主鍵。
1-1(A,B):
假設:
Assume A entity and B entity has 1-1 relationship, C is the actual table stored in the relational database taking A’s primary key as C’s primary key.轉換步驟:
The translation includes two steps as follows:o Step 1:
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
35
Generate C table by A table full outer join B table on A’s foreign key equals to B’s primary key.
o Step 2:
Execute entity(C) which accept C table as input and produce an HTable HC.
從以上的轉換規則我們得到 HA 如圖 11 所示,HA 拿 A 的主鍵當 RK 然後保 留 B 的所有 Field 在 HA 的 A_INFO 中。
第三段 一對多關係轉換
圖 12. 一對多關係轉換示意圖
在一對多的關係中,一方對於多方來說是一對一的關係。因此,對於這樣的 關係我們可以先對多方進行一對一的轉換,也就是 1-1(B, A),而得到 HB 如圖 12 所示。HB 紀錄了 B 連結 A 的外鍵所對應的資料,並使用 CF(A_INFO)來群組 A 的所有 Fields。
然而,在一方的觀點中我們必須去儲存多方的所有 Field,根據 HBase 的特性,
CQ 是可以彈性延伸的,適合用以處理一對多的關係。因此我們創建一個 CF 給每 個多方的 Field,然後以多方的 RK 來當作 CQ,儲存與多方的關係。這樣的轉換,
稱之為一對多關係轉換。然而,多方的 RK 可能會由多個 Fields 組成,且由於我們 使用 CQ 值來識別每筆多方資料的關係,CQ 值必須是唯一的。在這樣的情況之下,
就必須合併多方 RK Fields 的值而形成單一值,這與一對一中 RK 值的合併是相同 的。為了定義轉換的方便起見,我們首先定義一對多關係中一方的轉換規則-
‧
HA and HB is constructed for the mapping HTables in CDB.轉換步驟: as its foreign key.
o For each non-primary key field of , a key value pair is constructed with as its row key, the primary key as column qualifier in and take the value of as the value.
由上述的一對多轉換規則中可以得知一對多的轉換包含一方的轉換與多方的 轉換,一方的轉換與一對一關係的轉換規則相同。因此我們定義整個一對多的轉 換為 1-m-multi(A,B),轉換規則如下:
1-m -multi(A,B):
假設:
Assume A entity and B entity has 1-m relationship, A is the 1-side and B is the m-side.轉換步驟
The translation includes two steps as follows:o Step 1:
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
37
第四段 多對多關係轉換
圖 13. 多對多關係轉換示意圖
多對多的關係可以視為兩個一對多的關係。因此對 A 與 B 分別進行兩個一對 多的轉換。圖 13 中,A 與 B 擁有多對多的關係,其關係利用 table C 來記錄。經 過兩個一對多的轉換後,HA 利用兩個 CF:BE、BF 來保留 B 的 Fields 資訊,HB 則是利用 AD 與 AE 來保留 A 的 Fields 資訊。然而,我們仍然必須儲存 A 與 B 之 間關聯 table C 的額外資訊,如圖中的 C 的 Field CE。對於 table C 來說 A 與 C、B 與 C 也是一對多的關係,因此也必須針對 A 與 C、B 與 C 做一對多的轉換。在此 我們定義多對多轉換規則為 m-n(B,C),其規則如下:
m-n(A, B, C):
假設:
Assume A entity and B entity has m-n relationship, C is relational table generated by A and B.轉換步驟:
Execute 1-m(A, B), 1-m(B, A).
Execute 1-m(A, C), 1-m(B, C).‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
38
第五段 遞迴關係轉換
圖 14. 遞迴關係(R-R)轉換示意圖
第一段至第四段的轉換機制幾乎已經可以囊括所有的關係轉換,但是在 Google Bigtable 中提到,一個 table 應該要可以包含所有的資訊,為了增加效能,
使用者必須從一次性的讀取中取得所需的資料。
也就是說假如有 A、B、C 三個 table,A 與 B 有一對多的關係,B 對 C 也有 一對多的關係,我們希望透過 A 來取得 C 的資訊。雖然在上述的 4 項轉換規則中 已經將所有的關係描述定義了,但為了增加效能,有別於過去的多個 table join,
我們希望能夠透過一次性的讀取取得需要的資料。意即,能夠透過一次性的讀取 A 就取得 C 的資料,這樣一來 A 就必須保留 C 的資訊。上述的 ABC 關係,稱之 為遞迴關係。
我們可以將遞迴關係解釋為多個一對多關係的連結,首先處理所有 table 一對 多關係的轉換。如圖 14 所示,我們可以發現 HTable HB 儲存了對應的 C 的所有 資訊。對於 A 來說識別 C 的資訊必須透過 B,因此透過 B 與 C 主鍵的結合可以
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
39
用來識別相對應的 C 關係。又 C 對於 A 來說也是多方的關係,因此可以拿 C 的 Fields 來當作 A 的 CF,B 與 C 主鍵的結合來當作 CQ。以上的動作可以透過遞迴 地 Full outer join 的所有子 table 的方式來達成。以上述的 ABC table 為例,首先創 建一個 table D 來暫時儲存 full outer join 的結果。再遞迴地把 D full outer join 子 tables(table B、table C),如此一來 table D 便會是一張以 A 為主鍵並包含 C Fields 的大表,只要透過存取這張大表即可取得 C 之資訊。最後再對這張大表進行實體
用來識別相對應的 C 關係。又 C 對於 A 來說也是多方的關係,因此可以拿 C 的 Fields 來當作 A 的 CF,B 與 C 主鍵的結合來當作 CQ。以上的動作可以透過遞迴 地 Full outer join 的所有子 table 的方式來達成。以上述的 ABC table 為例,首先創 建一個 table D 來暫時儲存 full outer join 的結果。再遞迴地把 D full outer join 子 tables(table B、table C),如此一來 table D 便會是一張以 A 為主鍵並包含 C Fields 的大表,只要透過存取這張大表即可取得 C 之資訊。最後再對這張大表進行實體