前言:資料傾斜是日常大資料查詢中**的乙個bug,遇不到它時你覺得資料傾斜也就是書本部落格上的乙個無病呻吟的偶然案例,但當你遇到它是你就會懊悔當初怎麼不多了解一下這個赫赫有名的事故。
當然你和資料傾斜的緣分深淺還是看你公司的業務邏輯和資料量有沒有步入資料傾斜的領地。
說明:關於資料傾斜的產生原因我將結合 map 和 reduce 階段中的 shuffle 來講解,若是對 shuffle 有所忘記需要溫故的請到mapreduce解決資料傾斜的問題 進行相關了解。另本人能力有限,僅根據自己所了解的知識回答,若有誤處或不足之處望不吝指出。
一、什麼是資料傾斜以及資料傾斜是怎麼產生的?
簡單來說資料傾斜就是資料的key 的分化嚴重不均,造成一部分資料很多,一部分資料很少的局面。
舉個 word count 的入門例子,它的map 階段就是形成 (「aaa」,1)的形式,然後在reduce 階段進行 value 相加,得出 「aaa」 出現的次數。若進行 word count 的文字有100g,其中 80g 全部是 「aaa」 剩下 20g 是其餘單詞,那就會形成 80g 的資料量交給乙個 reduce 進行相加,其餘 20g 根據 key 不同分散到不同 reduce 進行相加的情況。如此就造成了資料傾斜,臨床反應就是 reduce 跑到 99%然後一直在原地等著 那80g 的reduce 跑完。
簡化了的 shuffle 圖就是這樣。
這樣就能清楚看到,資料經過 map後,由於不同key 的資料量分布不均,在shuffle 階段中通過 partition 將相同的 key 的資料打上發往同乙個 reducer 的標記,然後開始 spill (溢寫)寫入磁碟,最後merge成最終map階段輸出檔案。
如此一來 80g 的 aaa 將發往同乙個 reducer ,由此就可以知道 reduce 最後 1% 的工作在等什麼了。
二、為什麼說資料傾斜與業務邏輯和資料量有關?
從另外角度看資料傾斜,其本質還是在單台節點在執行那一部分資料reduce任務的時候,由於資料量大,跑不動,造成任務卡住。若是這台節點機器記憶體夠大,cpu、網路等資源充足,跑 80g 左右的資料量和跑10m 資料量所耗時間不是很大差距,那麼也就不存在問題,傾斜就傾斜吧,反正機器跑的動。所以機器配置和資料量存在乙個合理的比例,一旦資料量遠超機器的極限,那麼不管每個key的資料如何分布,總會有乙個key的資料量超出機器的能力,造成 reduce 緩慢甚至卡頓。
分組 注:group by 優於distinct group三、如何處理資料傾斜問題呢?情形:group by 維度過小,某值的數量過多
後果:處理某值的reduce非常耗時
去重 distinct count(distinct xx)
情形:某特殊值過多
後果:處理此特殊值的reduce耗時
連線 join
情形1:其中乙個表較小,但是key集中
後果1:分發到某乙個或幾個reduce上的資料遠高於平均值
情形2:大表與大表,但是分桶的判斷欄位0值或空值過多
後果2:這些空值都由乙個reduce處理,非常慢
1、調優引數
set hive.map.aggr=true;
set hive.groupby.skewindata=true;
好多同學使用這兩個引數的次數真的很多,但是他們不了解這兩個引數是怎麼解決資料傾斜的,從哪個角度著手的。
hive.groupby.skewindata=true:資料傾斜時負載均衡,當選項設定為true,生成的查詢計畫會有兩個mrjob。第乙個mrjob 中,map的輸出結果集合會隨機分布到reduce中,每個reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的groupby key有可能被分發到不同的reduce中,從而達到負載均衡的目的;第二個mrjob再根據預處理的資料結果按照groupby key分布到reduce中(這個過程可以保證相同的groupby key被分布到同乙個reduce中),最後完成最終的聚合操作。
由上面可以看出起到至關重要的作用的其實是第二個引數的設定,它使計算變成了兩個mapreduce,先在第乙個中在 shuffle 過程 partition 時隨機給 key 打標記,使每個key 隨機均勻分布到各個 reduce 上計算,但是這樣只能完成部分計算,因為相同key沒有分配到相同reduce上,所以需要第二次的mapreduce,這次就回歸正常 shuffle,但是資料分布不均勻的問題在第一次mapreduce已經有了很大的改善,因此基本解決資料傾斜。
2、在 key 上面做文章,在 map 階段將造成傾斜的key 先分成多組,例如 aaa 這個 key,map 時隨機在 aaa 後面加上 1,2,3,4 這四個數字之一,把 key 先分成四組,先進行一次運算,之後再恢復 key 進行最終運算。
3、能先進行 group 操作的時候先進行 group 操作,把 key 先進行一次 reduce,之後再進行 count 或者 distinct count 操作。
4、join 操作中,使用 map join 在 map 端就先進行 join ,免得到reduce 時卡住。
以上4中方式,都是根據資料傾斜形成的原因進行的一些變化。要麼將 reduce 端的隱患在 map 端就解決,要麼就是對 key 的操作,以減緩reduce 的壓力。總之了解了原因再去尋找解決之道就相對思路多了些,方法肯定不止這4種。
還有兩點補充:
2. 區域性聚合加全域性聚合。第二種方法進行兩次mapreduce,第一次在map階段對那些導致了資料傾斜的key 加上1-n的隨機字首,這樣之前相同的key 也會被分到不同的reduce中,進行聚合,這樣的話就有那些傾斜的key進行區域性聚合,數量就會大大降低。然後再進行第二次mapreduce這樣的話就去掉隨機字首,進行全域性聚合。這樣就可以有效地降低mapreduce了。不過進行兩次mapreduce,效能稍微比一次的差些。
四、總結
資料key分布不均的問題導致了之後一系列變化,如何使最後的結果變得有利,那就得先了解過程,然後自己引導變化使它朝有利的方向走去。
如何解決併發
雖然從巨集觀上,處理器是並行處理多項任務,但本質上乙個處理器在某個時間點只能處理乙個任務,屬於序列執行。在單處理器的情況下,併發問題源於多道程式設計系統的乙個基本特性 程序的相對執行速度不可 它取決於其他程序的活動 作業系統處理中斷的方式以及作業系統的排程策略。在分布式環境下,併發產生的可能性就更大...
如何解決藍屏問題
第一步 公升級筆記本bios 一般說來筆記本在出廠的時候很可能設計上存在某些的瑕疵,而廠商通常會採用公升級bios的方法來解決這些bug。如果我們在使用筆記本腦的過程中遇到了藍屏的情況,那麼我們可以採取公升級bios的辦法來解決藍屏的故障。第二步 正確安裝硬體驅動 在重新整理了bios以後,部分筆記...
如何解決「重複定義」
標頭檔案中一般只包含宣告,不包含變數的定義,如果沒辦法必須在標頭檔案中包含定義的話,多次引用該標頭檔案時,常遇到函式或者變數被重複定義的錯誤,比喻file1.h中定義了int a file2.h中也定義了 int a 此時在file.c中既包含file1.h也包含file2.h,在預編譯是,file...