開源交流丨批流一體資料整合框架ChunJun資料傳輸模組詳解分享

數棧DTinsight發表於2022-08-24

課件獲取:關注公眾號 “ChunJun”,後臺私信 “課件” 獲得直播課件

影片回放:

ChunJun 開源專案地址:  丨  gitee 喜歡我們的專案給我們點個__ STAR!STAR!!STAR!!!(重要的事情說三遍)__

技術交流釘釘 qun:30537511

本期我們帶大家回顧一下六六同學的直播分享《ChunJun 資料傳輸模組介紹》。

一、ChunJun 資料型別轉換

1、型別轉換解決的問題

大家一聽到「ChunJun 資料型別轉換」這個概念,可能會聯想到上下游之間進行資料互動時會涉及到的隱式轉換。如果上游和下游資料型別一致,則不需要對資料進行任何干預,直接進行下發即可。

但是大多數情況下會涉及到兩個問題,一是上游的資料來源型別和下游的資料來源型別不一致。比如 MySql 的 varchar 型別要寫到 HdfsOrc 檔案裡的 string 型別的話,在上游的表示是 varchar,在下游的表示是 string,但實際上中間段 java 的型別都是 string。

另外一種情況則是,上下游之間不止資料來源型別不一樣,資料型別也不一樣,除了要做型別的對映之外,還需要對資料本身進行改動。比如,MySql 的 date 型別要寫到下游 timestamp 型別,我們需要進行的操作是把 date 中的毫秒級的時間戳拿出來,轉換成 timestamp 的型別,再往下游去寫。

這樣就引出了一個問題,如何建立所有資料來源型別之間的對映 / 轉換關係?下面將為大家解答這個問題。

file

2、型別對映概覽

・client 端:在 Factory 類中透過 RawConverter 類建立對映關係

・source 端:將資料封裝成 AbstractBaseColumn

・sink 端:透過 AbstractBaseColumn 中的轉換方法將資料轉換成對應型別

file

ChunJun 目前支援的資料型別對映關係圖如下:

file

3、型別對映詳解

以 Timestamp 為例,如果要寫入到 Long 型別的話,根據上文展示的 ChunJun 資料型別對映關係圖,最終對映到 TimestampColumn 中,具體流程如下圖:

file

上面這個例子描述的是一個單獨的欄位,正常情況下,會處理多個欄位,這時的型別對映詳解情況如下圖:

file as 方法就是資料型別轉換的方法。使用這個機制之後,在下游可以只關心需要的資料型別,增加開發效率。

二、ChunJun 資料傳輸過程

瞭解完 ChunJun 資料型別轉換後,我們來為大家分享 ChunJun 的資料傳輸過程。

1、上下游資料傳輸方式

在 ChunJun 中進行同步作業,有兩種情況,一是運算元鏈開啟的情況,上游的 Source 和下游的 Sink 會被合併成一個 task,有同一個執行緒去做排程;二是把運算元鏈進行關閉,Source 和 Sink 各自形成一個 task,也有各自的執行緒去進行排程。

在運算元鏈開啟的情況下,上下游資料傳輸方式可分為兩種,物件重用和複製。

● 物件重用

・上下游資料傳輸使用方法呼叫的形式,將上游產生的資料的物件引用直接交給下游

・上下游運算元需要形成運算元鏈,作業開啟物件重用

· env.getConfig().enableObjectReuse();

● 複製

・上游傳輸給下游的資料,需要經過一次深複製

・上下游運算元需要形成運算元鏈

運算元鏈的好處是可以減少序列化的操作,那麼為什麼我們還要引入序列化呢?因為 ChunJun 的特殊性。ChunJun 同步作業的話,只有上下游兩個運算元,且都對接了正式的資料來源,讀寫的時候會導致執行緒堵塞。因此上限由網路 io 決定,如果斷開運算元鏈,cpu 會在一端執行緒阻塞的時候切換到另外一端。在序列化的效能較高時,執行緒上下文切換帶來的效能下降完全可以被彌補。

經過測試,序列化的效能比物件重用和複製高 30% 左右。

● 序列化

・上下游資料傳輸依賴於網路傳輸。上游資料進行序列化成 byte 陣列後進行網路傳輸,下游收到資料後需要進行反序列化

・上下游之間不形成運算元鏈

file

知道要做序列化後,會產生一些思考,帶著這些疑問,接著往下看。

・序列化和反序列化在什麼時候發生?

・Flink 支援哪些序列化?

・序列化是怎麼做的?

・怎麼找到適合的序列化方式?

・如何實現自定義的序列化?

2、序列化傳輸過程

下圖是 ChunJun 在進行序列化操作時的資料傳輸鏈路圖:

file

3、DataOutView

file

4、TypeInformation 介紹

file

5、kryo 序列化 & BaseSerializer

同樣是序列化一個 int 物件,對 kryo 來說,首先需要知道它的型別,然後從高位到低位依次去寫入。

DataOutputView 則是直接呼叫一個 writeInt 的方法,寫一句關鍵程式碼即可:

UNSAFE.putInt(

this.buffer,

BASE_OFFSET + this.position, v);

file

三、ChunJun 序列化實現

1、ColumnRowData 序列化過程

ColumnRowData 序列化過程採取標誌位 + 實際資料的方式,具體流程如下圖:

file

相對於 kryo 的序列化來說:

・實現了更密集的儲存

・相容 null 值

・減少了不必要的資料傳輸

2、BinaryRowData 結構

file 因為資料區一格只佔 8 個位元組,且每個 index 只能佔到一位,所以肯定存在一些沒法儲存在 8 位元組範圍之內的資料,可變長度部分就是用來存放資料區無法存放的資料。

3、BinaryRowData-setNull 操作

看到上文的 null 值判斷區,有些同學可能會好奇這是什麼,又是怎麼進行操作的。下圖將對一個下標為 11 的資料去做 setnull 操作,進行簡單介紹:

file

4、BinaryRowData 資料儲存方式

file



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69995740/viewspace-2911756/,如需轉載,請註明出處,否則將追究法律責任。

相關文章