Flink如何操作二元資料

本篇概要介紹Flink怎麼利用序列化(Serilization)操作二元資料(Byte arrays),概略流程如下圖:

螢幕截圖 2016-01-24 18.14.19.png

讀取資料物件時,會先將資料物件序列化(Serialization)到Flink特製的記憶體區塊(Memory segments)。當記憶體滿時,會把記憶體區塊實體化到檔案系統。反之亦然,也就是把資料從檔案系統讀出,變成記憶體區塊,然後反序列化成資料物件。

這樣做最明顯的好處在於能夠直接操作二元資料,更有效率的處理記憶體,帶來優越的效能。原文出處- (http://flink.apache.org/news/2015/05/11/Juggling-with-Bits-and-Bytes.html, 作者:fhueske,citing and modifying figures in this article is accepted by the original author)

序列化/反序列化

Flink會把物件序列化成二元資料(Byte arrays)到記憶體中;反之,當要寫資料時,Flink會把二元資料反序列化成物件。如果記憶體滿了,就會IO到硬碟中。

我們實際看個序列化的例子,Tuple是Flink最常見的資料型態,下例的Tuple3可為1,50000,(1234456,Codd)

Tuple3<Integer, Double, Person>

public class Person {
    public int id;
    public String name;
}

上面的Tuple3,其中的Integer會被序列化成Flink特製的記憶體區塊的位址,Double、Person也是。對於非固定長度的資料型態如String有另外的處理方式。

下圖右上的長方形是邏輯式的資料物件結構,箭頭所指為在記憶體中實際存取的方式。

螢幕截圖 2016-01-24 18.22.00.png

 

例如Integer使用了4Bytes,Double使用了8Bytes,而String則用了不固定的大小。也就是說,序列化會針對不同資料型態做不同的處理(原始碼: https://github.com/apache/flink/blob/release-0.9.0-milestone-1/flink-core/src/main/java/org/apache/flink/api/common/typeinfo/TypeInformation.java)

根據資料型態序列化成二元資料,此動作類似於資料庫理論中資料表的綱要(Schema),不同資料型態會消耗不同大小、並且能夠是固定大小或是變動大小的儲存空間。例如Int是固定大小,String則是變動大小。(關鍵字:Fix-length & Variable-length)

序列化資料後,根據Tuple的定義知道該資料型態佔用多少記憶體,所以一旦知道Tuple的記憶體位址,就知道該Tuple哪個欄位的資料存在哪個記憶體位址。原始碼: https://github.com/apache/flink/blob/release-0.9.0-milestone-1/flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java

目前Google’s Protobuf、Apache Avro等都有函式庫能夠序列化物件,Flink則是特製了自己的方式,因為進行操作資料時,知道二元資料的序列化處理方式非常重要,並且很大的影響了效能,我們看下面的例子。

序列化之後,如何操作資料?

我們用排序的例子演示具體的二元資料是如何操作的。當排序演算法準備開始時,從下圖左方資料物件開始進入,Flink特製的記憶體區塊會被放到緩衝區。緩衝區分為兩個部份,一部份實際存著所有的二元資料,如下圖下方的Memory Segment。另一部份只存著二元資料的位址標的(可以類比為指標)與Key(可以想成一對Key,Value),如下圖上方。分成兩個區塊的目的在於免去資料的實際移動,而只需要更改指標位置,以此增加運算效率。

螢幕截圖 2016-01-24 18.27.36.png

進行排序比較時,只對Key做比較及排序(例如Quicksort ),也就是只對下圖上方的區塊進行搬移。而下圖下方的整筆資料是固定不動的。當然,如果Key不能比較的話,還是必須把物件反序列化(Deserialize)之後拿出來對比。

螢幕截圖 2016-01-24 18.31.38.png

對Key排序結束後,直接循序讀取,再依位址指標讀出整筆資料,就能得到排序後的結果,如下圖所示。

螢幕截圖 2016-01-24 18.44.26.png

這種把物件序列化成二元資料的處理方式,除了排序以外,也增進其他資料操作的效能,例如合併資料時的效能。相關文章: https://flink.apache.org/news/2015/03/13/peeking-into-Apache-Flinks-Engine-Room.html

結果比較

原作者與把Java原有方式、Flink在大量的資料處理下比較(一千萬筆tuples)。結果顯示序列化來處理資料,除了大幅減少執行時間,也能穩定的用較少的memory、以及很少的garbage collection。

原作者的講解影片-

 

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s