1. 程式人生 > >MR的shuffle和Spark的shuffle之間的區別

MR的shuffle和Spark的shuffle之間的區別

solid combine 大量 數據 文件 分區 小文件 位置 task創建

mr的shuffle
mapShuffle
數據存到hdfs中是以塊進行存儲的,每一個塊對應一個分片,maptask就是從分片中獲取數據的
在某個節點上啟動了map Task,map Task讀取是通過k-v來讀取的,讀取的數據會放到環形緩存區,這樣做的目的是為了防止IO的訪問次數,然後環形緩存區的內存達到一定的閥值的
時候會把文件益寫到磁盤,溢出的各種小文件會合並成一個大文件,這個合並的過程中會進行排序,這個排序叫做歸並排序
map階段會涉及到
1.sort排序(默認按字典排序)
2.合並(combiner合並)
3.文件合並(merage 合並 總共有三種,默認是內存到磁盤)
4.壓縮(設置壓縮就會執行)


reduce Shuffle
歸並排序完成後reduce端會拉取map端的數據,拉取的這個過程叫做copy過程,拉取的數據合並成一個文件,GroupComparator(默認,這個我們也可以自定義)是專門對文件夾裏面的key進行分組
然後就形成k-List(v1,v2,v3)的形式,然後reduce經過業務處理,最終輸出到hdfs,如果設置壓縮就會執行,不設置則不執行
reduce階段會涉及到:
1.sort排序
2.分組(將相同的key的value放到一個容器的過程)
3.merge文件合並

4.壓縮


spark shuffle的版本一
1.rdd中一個partition對應一個shufflemapTask任務,因為某個節點上可以有多個分區,所以可以有多個shufflemapTask


2.每一個shufflemapTask都會為每一個resultTask創建一個bucket緩存(內存),bucket的數量=M x R,當內存達到一定值的時候會益寫到shuffleblockfile文件中
3.shuffleMap task會封裝成一個叫mapStatus,這個mapstatus裏面包含了每一個resultTask拉取數據的大小
Mapstatus: 是ShuffleMapTask返回調度器scheduler的對象,包括任務運行的塊管理器地址和對應每個reducer的輸出大小。
如果partitions的數量大於2000,則用HighlyCompressedMapStatus,否則用CompressedMapStatus。

4.每一個resultTask拉取過來的數據,就會在內部形成一個rdd,這個rdd叫做shuffleRdd,這個rdd的數據優先存放到內存中,內存中不夠然後存到磁盤裏
如果是groupByKey算子就結束了,下次執行ReduceByKey的時候,再進行相同key的聚合操作,這個時候會把shuffle rdd進行聚合操作生成mapPartitionRdd,就是我們執行reduceByKey之後得到的那個rdd
spark shuffle的版本二
版本一的缺點:版本一的shuffle方式中會產生大量的小文件,
版本二的優點:就是為了減少這麽多小文件的生成
bucket的數量=cpu*resultTask的個數
版本二設計的原理:一個shuffleMapTask還是會寫入resultTask對應個數的本地文件,但是當下一個shuffleMapTask運行的時候會直接把數據寫到之前已經建立好的本地文件,這個文件可以復用,這種復用機制叫做consolidation機制
我們把這一組的shuffle文件稱為shuffleGroup,每個文件中都存儲了很多shuffleMapTask對應的數據,這個文件叫做segment,這個時候因為不同的shuffleMapTask都是存在一個文件中
所以建立索引文件,來標記shuffleMapTask在shuffleBlockFile的位置+偏移量,這樣就可以在一個文件裏面把不同的shuffleMaptask數據分出來
spark shuffle的版本三
版本三的優點:是通過排序建立索引,相比較於版本二,它只有一個臨時文件,不管有多少個resultTask都只有一個臨時文件,
缺點:這個排序操作是一個消耗CPU的操作,代價是會消耗很多的cpu
版本二占用內存多,打開文件多,但不需排序,速度快。版本三占用內存少,打開文件少,速度相對慢。實踐證明使用第二種方案的應用場景更多些。
shuffle的讀流程
1.有一個類blockManager,封裝了臨時文件的位置信息,resultTask先通過blockManager,就知道我從哪個節點拿數據
如果是遠程,它就是發起一次socket請求,創建一個socket鏈接。然後發起一次遠程調用,告訴遠程的讀取程序,讀取哪些數據。讀到的內容再通過socket傳過來。
2.一條條讀數據和一塊塊讀數據的優缺點?
如果是一條條讀取的話,實時性好,性能低下

一塊塊讀取的話性能高,但是實時性不好

Shuffle讀由reduce這邊發起,它需要先到臨時文件中讀,一般這個臨時文件和reduce不在一臺節點上,它需要跨網絡去讀。但也不排除在一臺服務器。不論如何它需要知道臨時文件的位置,
這個是誰來告訴它的呢?它有一個BlockManager的類。這裏就知道將來是從本地文件中讀取,還是需要從遠程服務器上讀取。
讀進來後再做join或者combine的運算。
這些臨時文件的位置就記錄在Map結構中。
可以這樣理解分區partition是RDD存儲數據的地方,實際是個邏輯單位,真正要取數據時,它就調用BlockManage去讀,它是以數據塊的方式來讀。
比如一次讀取32k還是64k。它不是一條一條讀,一條一條讀肯定性能低。它讀時首先是看本地還是遠程,如果是本地就直接讀這個文件了,
如果是遠程,它就是發起一次socket請求,創建一個socket鏈接。然後發起一次遠程調用,告訴遠程的讀取程序,讀取哪些數據。讀到的內容再通過socket傳過來。

MR的shuffle和Spark的shuffle之間的區別