2011-09-12 30 views
4

我已經開始使用以JSON格式到達的大型數據集。不幸的是,提供數據饋送的服務提供了不平凡數量的重複記錄。另一方面,每條記錄都有一個唯一的Id號碼存儲爲64位正整數(Java long)。如何從大數據饋送中排除重複記錄?

數據每週到達一次,每次交付約爲10M條記錄。我需要排除當前交付中的重複項以及之前批次中的記錄。

攻擊重複數據刪除問題的蠻力方法是將Id號碼推送到Java Set。由於設置接口需要唯一性,插入過程中的失敗將表明重複。

現在的問題是:有沒有更好的方法來尋找重複的作爲我導入記錄?

我正在使用Hadoop來挖掘數據,所以如果有一種很好的方法可以使用Hadoop來重複記錄,那將是一種獎勵。

回答

5

您可以創建一個MapReduce任務,其中地圖輸出具有唯一ID號的密鑰嗎?這樣,在你的reduce任務中,你將傳遞一個具有該ID號的所有值的迭代器。只輸出第一個值,減少的輸出將不會有重複。

+0

這是比Rolands更好的解決方案。 –

+1

@salexander - 我可以爲新批數據做到這一點,但是如何識別前幾周現有記錄的重複項。例如,以前的數據有ID [1..10];新數據包含[11,11,9]。 map/reduce作業會找到重複的11,但9在這個集合中是唯一的,但與整個集合相比不是這樣。我知道我可以重新運行整個數據集,但這看起來很愚蠢。 – gras

+0

在這種情況下,我們需要將所有密鑰放在一個簡化器中,這可能會減慢過程 – sunitha

1

讓我看看。每個java.lang.Long需要24個字節。每個HashMap$Entry也需要24個字節,並且HashMap的數組需要4個字節。所以你有52 * 10M = 512M的地圖堆存儲空間。儘管如此,這是一週的10M記錄。

如果您使用的是64位系統,則可以將堆大小設置爲5 GB,然後查看得到的結果。

應該有一個java.util.Set的其他實現,每個條目只消耗大約16個字節,因此您可以像處理java.util.HashSet一樣處理三倍的數據。我自己寫了一篇,但我無法分享。您可以嘗試使用GNU Trove。

0

您必須保留HDFS中的唯一標識列表,並在每批加載後重建它。

由於您的案例中的基數非常大(您可以預計一年內> 1B的唯一記錄),您的唯一ID列表需要拆分爲多個部分,比如N。分區算法是特定於域的。在一般的方法是ID轉換爲長的散列字符串(16個字節是OK),並創建2 ^ķ桶:

對於k = 8,例如:

桶#1包含其哈希值開始的所有ID 0 桶#2包含其散列值開始的所有ID與1 ... 鬥#256包含其散列值255

開始您收到第一次運行重複數據刪除作業每一批新的所有ID:地圖讀取記錄,取記錄ID,將其散列並輸出Key = bucket#(在我們的例子中爲0..255)和Value = ID。每個Reducer接收給定桶的所有IDS。 Reducer將系統中已知的給定桶的所有唯一ID加載到內部Set中,並使用此內部Set來檢查所有輸入記錄ID。如果記錄有尚未知道的ID,則更新內部設置並輸出記錄。

在縮小器關閉時輸出內部將唯一ID集返回到HDFS。

通過將整套ID分成多個桶,您可以創建可以很好擴展的解決方案。