Hadoop MapReduce進階 使用分散式快取進行replicated join

風的王子發表於2013-10-29

概念:

reduce-side join技術是靈活的,但是有時候它仍然會變得效率極低。由於join直到reduce()階段才會開始,我們將會在網路中傳遞shuffle所有資料,而在大多數情況下,我們會在join階段丟掉大多數傳遞的資料。因此我們期望能夠在map階段完成整個join操作。

主要技術難點:

在map階段完成join的主要困難就是mapper可能需要與一個它自己不能獲得的資料進行join操作,如果我們能夠保證這樣子的資料可被mapper獲得,那我們這個技術就可用。舉個例子,如果我們知道兩個源資料被分為同樣大小的partition,而且每個partition都以適合作為join key的key值排序的話,那每個mapper()就可以獲取所有join操作需要的資料。事實上,Hadoop的org.apache.hadoop.mared.join包中包含了這樣的幫助類來實現mapside join,但不幸的是,這樣的情況太少了。而且使用這樣的類會造成額外的開銷。因此,我們不會繼續討論這個包。

什麼情況下使用?

情況1:如果我們知道兩個源資料被分為同樣大小的partition,而且每個partition都以適合作為join key的key值排序

情況2:當join大型資料時,通常只有一個源資料十分巨大,另一個資料可能就會呈數量級的減小。例如,一個電話公司的使用者資料可能只有千萬條使用者資料,但他的交易記錄資料可能會有十億條數量級以上的具體電話記錄。當小的資料來源可以被分配到mapper的記憶體中時,我們可以獲得效果明顯的效能提高,只要通過將小的資料來源拷貝到每一臺mapper機器上,使mapper在map階段就進行join操作。這個操作就叫做replicate join。

解決方案:

Hadoop有一個叫做分散式快取(distributed cache)的機制來將資料分發到叢集上的所有節點上。它通常用來分發所有mapper需要的包含“background”資料的檔案。例如你使用Hadoop來分類文件,你可能會有一個關鍵字的列表,你將使用distributed cache來保證所有mapper能夠獲得這些keywords("background data")。
操作步驟:
1.將資料分發到每個節點上:
  1. DistributedCache.addCacheFile(new Path(args[0]).toUri(), conf);  
2.在每個mapper上使用DistributedCache.getLocalCacheFiles()來獲取檔案,之後再進行相應的操作:
  1. DistributedCache.getLocalCacheFiles();   

新出現的問題:

我們的又一個限制是我們其中一個join的表必須足夠小以至於能儲存到記憶體中。儘管在不對稱大小的輸入資料中,較小的那個資料可能仍然不夠小(不夠小到可以放入記憶體中。)
1.我們可以通過重新安排資料加工步驟來使它們有效。例如:如果你需要一個所有使用者在415區的排序資料時,在濾除一定記錄前就將Orders以及Customers表連線起來雖然正確,但是效率卻不高。Customers和Orders表都可能大到不能放入記憶體中。此時我們可以預處理資料使Customers或者Orders表變小。
2.有時候我們不論怎樣預處理資料都不能使資料足夠小,那我們應該在map時過濾掉不屬於415 area的使用者。詳見《Hadoop in Action》 Chapter5.2.3 semijoin




轉載:http://blog.csdn.net/jokes000/article/details/7084351

相關文章