今天在對鎢絲計劃思考的基礎上,講解下基於Tungsten的shuffle。數組
首先解釋下概念,Tungsten-sort是對普通sort的一種優化,排序的不是內容自己,而是內容序列化後字節數組的指針(元數據),把數據的排序轉變爲了指針數組的排序,實現了直接對序列化後的二進制數據進行排序。因爲直接基於二進制數據進行操做,因此在這裏面沒有序列化和反序列化的過程。內存的消耗大大下降,相應的,會極大的減小的gc的開銷。數據結構
要作到這種,jvm的內存管理結構沒法完成,因此提出了Page的概念。jvm
Page是由block組成的,咱們先看一下Block的結構,能夠看到,除了記錄page編號外,Block內部組成是MemoryLocation。
大數據
在MemoryLocation中,重要的就是記錄了對象及初始位置的定位offset。實際運行能夠onheap或者offheap(用NIO或者Tachyon管理)。優化
在shuffle角度,都是統一在SortShuffleManager中進行構造。能夠看到,在以下位置構造了UnsafeShuffleWriter,但沒有UnsafeShuffleReader,從Tungsten角度講,reader使用的是HashShuffleReader。
spa
從註釋中,能夠看到數據一旦進來,就使用shuffle write進行序列化,在序列化的二進制基礎上進行排序,這樣就能夠減小內存的GC。這種優化須要咱們的序列化器能夠在不反序列化的狀況下從新排序。
指針
讓咱們進入UnsafeShuffleWriter對象
會經過MyByteArrayOutputStream直接對內存操做
排序
在write方法中,會循環記錄,寫入Sorter。
ip
其中,serBuffle默認大小是1M,並且已是序列化以後的數據了。
在插入前,首先會分配內存,以後會根據每條數據,採用遊標的方式進行遍歷,並計算找到recordAddress,完成插入操做。
在內存分配時,會有兩種分配方式UNSAFE和HEAP,內部各有一套本身的內存評估機制
此外,recordAddress是有一套本身的編解碼方式。
最終在插入時,僅僅是存放了一個RecordPointer,也就是數據指針。
在具體插入操做的時候,以Page爲核心單位,從Page角度講,插入記錄的時候,自己也有location和大小,須要找到page中指針的位置。在整個內存中有多個Page,每一個Page有限定的大小,滿了以後會分配下一個Page。從jvm角度講,最底層的數據結構是字節數組,因此outputStream和序列化都是對字節數組來操做的。進行shuffle操做的時候,實際是對指針進行操做,這是沒有序列化和反序列化的關鍵。數據量也少,因此內存使用率低,大大減小了GC。
最後,說明下,即便配置了Tungsten shuffle,在一些狀況也會自動變成sort-based shuffle,從數據結構角度講,限制蠻多,記錄不能太大,單條記錄不能超過128M,shuffle的時候中間過程不能產生太多的小文件,不能超過160W,aggregation或者輸出後須要排序的操做也不能夠。
DT大數據天天晚上20:00YY頻道現場授課頻道68917580