Hadoop Shuffle和Spark Shuffle的區別
阿新 • • 發佈:2018-12-25
一.MR的Shuffle mapShuffle 資料存到hdfs中是以塊進行儲存的,每一個塊對應一個分片,maptask就是從分片中獲取資料的 在某個節點上啟動了map Task,map Task讀取是通過k-v來讀取的,讀取的資料會放到環形快取區,這樣做的目的是為了防止IO的訪問次數,然後環形快取區的記憶體達到一定的閥值的 時候會把檔案益寫到磁碟,溢位的各種小檔案會合併成一個大檔案,這個合併的過程中會進行排序,這個排序叫做歸併排序 1.1map階段會涉及到 1.1.1.sort排序(預設按字典排序) 1.1.2.合併(combiner合併) 1.1.3.檔案合併(merage 合併 總共有三種,預設是記憶體到磁碟) 1.1.4.壓縮(設定壓縮就會執行) reduce Shuffle 歸併排序完成後reduce端會拉取map端的資料,拉取的這個過程叫做copy過程,拉取的資料合併成一個檔案,GroupComparator(預設,這個我們也可以自定義)是專門對資料夾裡面的key進行分組 然後就形成k-List(v1,v2,v3)的形式,然後reduce經過業務處理,最終輸出到hdfs,如果設定壓縮就會執行,不設定則不執行 1.2 reduce階段會涉及到: 1.2.1.sort排序 1.2.2.分組(將相同的key的value放到一個容器的過程) 1.2.3.merge檔案合併 1.2.4.壓縮 二.spark shuffle的版本一 2.1.rdd中一個partition對應一個shufflemapTask任務,因為某個節點上可以有多個分割槽,所以可以有多個shufflemapTask 2.2.每一個shufflemapTask都會為每一個resultTask建立一個bucket快取(記憶體),bucket的數量=M x R,當記憶體達到一定值的時候會益寫到shuffleblockfile檔案中 2.3.shuffleMap task會封裝成一個叫mapStatus,這個mapstatus裡面包含了每一個resultTask拉取資料的大小 2.4 Mapstatus: 是ShuffleMapTask返回排程器scheduler的物件,包括任務執行的塊管理器地址和對應每個reducer的輸出大小。 如果partitions的數量大於2000,則用HighlyCompressedMapStatus,否則用CompressedMapStatus。 2.5.每一個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.一條條讀資料和一塊塊讀資料的優缺點? 2.1如果是一條條讀取的話,實時性好,效能低下 2.2一塊塊讀取的話效能高,但是實時性不好 Shuffle讀由reduce這邊發起,它需要先到臨時檔案中讀,一般這個臨時檔案和reduce不在一臺節點上,它需要跨網路去讀。但也不排除在一臺伺服器。不論如何它需要知道臨時檔案的位置, 這個是誰來告訴它的呢?它有一個BlockManager的類。這裡就知道將來是從本地檔案中讀取,還是需要從遠端伺服器上讀取。 讀進來後再做join或者combine的運算。 這些臨時檔案的位置就記錄在Map結構中。 可以這樣理解分割槽partition是RDD儲存資料的地方,實際是個邏輯單位,真正要取資料時,它就呼叫BlockManage去讀,它是以資料塊的方式來讀。 比如一次讀取32k還是64k。它不是一條一條讀,一條一條讀肯定效能低。它讀時首先是看本地還是遠端,如果是本地就直接讀這個檔案了, 如果是遠端,它就是發起一次socket請求,建立一個socket連結。然後發起一次遠端呼叫,告訴遠端的讀取程式,讀取哪些資料。讀到的內容再通過socket傳過來。