2012-07-31 32 views

回答

2

你有兩個問題。首先,您要確保爲每個令牌分配一個唯一的ID。要做到這一點,您應該通過令牌對記錄進行排序和分組,並在減速器中進行分配。一旦確定了reducer方法對每個標記只調用一次,就可以使用上下文中的分區編號和reducer維護的唯一數字標識(每個分區一個實例) - 只需使用初始化爲1的實例變量在設置方法中並在減少方法中遞增。

0

爲了避免不屬於您業務邏輯的同步,排序和分組,您可以使用一些技巧,這會更快。

最簡單的是在Reducer中生成UUID,每個鍵一個UUID UUID.randomUUID(),但這些都不是數字。

如果你想要連續的數字ID序列,並且你的輸出足夠小,以便一個reducer進行處理,比通過org.apache.hadoop.mapreduce.Job.setNumReduceTasks(int tasks)強制一個reducer執行該作業,因此所有的鑰匙將被引導到一個單一的減速機。

如果Mapper的輸出對於單個Reducer來說仍然太大,並且您不關心ID的序列連續性或者您的字典可以被分區,那麼您可以使用Partitioner(see)的一些技巧。這個想法是,你可以在邏輯上將密鑰劃分成已知長度的N個範圍(例如,範圍1可以具有以1開始的1密耳密鑰,範圍4可以具有以3500000開始的500個ID等等)。邏輯:

  1. 將Reducers的數量設置爲N(JobConf.setNumReduceTasks(N));
  2. 執行與其範圍匹配鍵的分區程序,它將把所有鍵從相同的範圍指向相同的Reducer;
  3. 有減速之內與範圍內的第一個ID開始計數(在減少使用相同的邏輯的第一次調用,如分區,以確定其範圍是減速)

如果你沒有任何業務都您可以花費一些時間來了解關鍵區域,並計算範圍和長度。有了這個,你可以在結果集中獲得連續的id序列。

如果您不想花時間完成不同的鍵,那麼目標是爲每個具有不同數字的Reducer啓動ID(Reducer 1將生成僅以1(1,10,124523,1341243)開始的ID,減速器2與2(2,23,234234532)等)。 要做到這一點,計算密鑰的第一個字節的mod 10,並強制10減速器,直接零到同一分區爲1(主要原因是沒有2個數字的整數以0開頭,它可能會導致衝突來自其他分區的ID),因此分區0的輸出是空的。在reducer一側追加(連接2個字符串!!!)計數器到(mod 10的第一個字節),其中0變爲1.每個reducer都有一個從1到無窮大的計數器,可以從一個計數器初始化包含用於該分區的最後一個id的文件。

Ex。

key = "abc", ascii of 'a' is 97, 97 % 10 = 7 and id for that key is '7' + '1' = '71', 
for "asd" it will be '7' + '244' = '7244', 
for "bbv" is '8' + '1' = '81', 
for "bgh" is '8' + '2' = '82', 
for "ddv", 'd' is ascii 100, 100 % 100 = 0 , convert to 1, '1' + '1' = '11', 
for "edv" is 101 % 100 = 1, '1' + '2234' = '12234'. 

因爲所有的鍵具有不同的數字開始,他們從來沒有重疊,因此沒有必要多減速器之間進行同步。它通過字符串連接mod結果和計數器來保證,所以不會溢出到下一個前綴/前導數字。另一個優勢是你不需要做任何預分類,這不屬於你的商業邏輯。 當Reducer關閉時,它可以將用於生成id的最後一個計數器寫入文件,該文件可用於下次運行,並提供包含字典分區的ID的連續性。

爲了增加分區的數量從10到100使用模100,並用2位的人(我們再次浪費的10級減速器輸出)合併單位的結果。例如10%100 = 10,1%100 = 1轉換爲10,102%100 = 2通過在字符串中加'0'或乘以10來轉換爲20。目標是讓所有前綴具有相同的數字位數在這種情況下2.

隨着聰明邏輯我們能夠避免(在模100的情況下爲0,或1,2,9)浪費跳過分區。

警告:此邏輯易受數據傾斜影響。

我希望它的幫助下, 乾杯。

0

我們使用的另一個選項是將ID塊分配給任務,爲此,您需要一種管理事務的機制。我們使用AWS的SimpleDB來跟蹤已經使用或未使用的事務和ID。

在工作開始時,我們鎖定Simple DB上的整個ID塊集(只是將一個屬性更改爲'locked'),然後每個任務都調用簡單的db來'檢出'一個ID塊使用。

如果一個任務不會失敗它解鎖'塊,從不更新上次使用的ID,所以這些ID沒有被失敗的任務消耗。最後,當我們解鎖整個ID塊時,我們解鎖失敗任務所持有的任何東西。

我們將通過導入/導出,從簡單的DB的ID塊,以改善這個過程,所以我們並不需要更新的外部資源。相反,我們可以從與數據一起存儲的文件中讀取可用的ID,將它們寫入簡單的數據庫,使用簡單的數據庫來協調將塊分配給各個任務(映射器,縮減器),然後將它們寫回成功。

一旦我們作出這樣的改進,我們可能會公開提供的代碼,因此,如果任何人的興趣在這種方式隨時與我檢查在未來,如果我們完成了我會更新這個帖子與碼。