1. 程式人生 > >MapReduce數據傾斜的解決方式

MapReduce數據傾斜的解決方式

導致 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:

public
class 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數據傾斜的解決方式