MapReduce數據傾斜的解決方式
阿新 • • 發佈:2018-04-07
導致 multi job 自己 tin 用戶 接口 情況 class
數據傾斜:由於數據分布不均勻,造成數據大量的集中到一點,造成數據熱點。map /reduce程序執行時,reduce節點大部分執行完畢,但是有一個或者幾個reduce節點運行很慢,導致整個程序的處理時間很長,這是因為某一個key的條數比其他key多很多(有時是百倍或者千倍之多),這條key所在的reduce節點所處理的數據量比其他節點就大很多,從而導致某幾個節點遲遲運行不完,此稱之為數據傾斜。
Hadoop計算框架的特性:
- 不怕數據大,怕數據傾斜;
- job數比較多的作業運行效率相對比較低,如子查詢較多;
- 不會發生數據傾斜的情況:sum,count,max,min
會發生數據傾斜的情況:group by,count(distinct),小表關聯大表
MapReduce提供Partitioner接口,它的作用就是根據key或value及reduce的數量來決定當前的這對輸出數據最終應該交由哪個reduce task處理。默認對key hash後再以reduce task數量取模。默認的取模方式只是為了平均reduce的處理能力,如果用戶自己對Partitioner有需求,可以訂制並設置到job上。
用hadoop程序進行數據關聯時,常碰到數據傾斜的情況,這裏提供一種解決方法。
自己實現partition類,用key和value相加取hash值:
方式1:
源代碼: public int getPartition(K key, V value,int numReduceTasks) { return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks; } 修改後 public int getPartition(K key, V value, int numReduceTasks) { return (((key).hashCode()+value.hashCode()) & Integer.MAX_VALUE) % numReduceTasks; }
方式2:
publicclass HashPartitioner<K, V> extends Partitioner<K, V> { private int aa= 0; /** Use {@link Object#hashCode()} to partition. */ public int getPartition(K key, V value, int numReduceTasks) { return (key.hashCode()+(aa++) & Integer.MAX_VALUE) % numReduceTasks; }
優化常用手段:
- 減少job數(合並MapReduce,用Multi-group by)
- 設置合理的task數,能有效提升性能
- 數據量大,慎用count(distinct)
- 對小文件進行合並
MapReduce數據傾斜的解決方式