[英]Which data structure to use to store millions of objects in multithreading environment ( Scalability and performace )?
[英]Efficient Data Structure To Store Millions of Records
我有一個包含數百萬個記錄的輸入文件,每個記錄又包含數千個列,其中每個列都由定界符分隔。
記錄和列的數量可能因文件而異。
我有一個要求,我必須解析這些記錄並將它們存儲在java對象中,以便可以將其進一步傳遞給Drools Framework進行列級驗證。
這就是我的輸入數據和架構文件的樣子。
輸入文件 :
John|Doe|35|10 Floyd St|132|Los Angeles|CA|USA ... and so on
...
...
Millions records like this
架構文件:
firstName|String|false|20|NA
lastName|String|false|20|NA
age|Integer|false|3|NA
addressLine1|String|false|20|NA
addressLine2|String|false|20|NA
city|String|false|5|NA
state|String|false|10|NA
country|String|false|10|NA
我嘗試在地圖的幫助下實現此解決方案,並創建了一個包含該地圖的Java類。
class GenericRecord {
Map<String,FieldSpecification> properties; //used HashMap as an implementation
}
class FieldSpecification {
public String fieldName;
public String dataType;
public int length;
public String value;
public String format;
}
對於輸入文件中的覆蓋率行,我正在創建一個Record
對象,並使用map存儲其列的值。 除此之外,我還在FieldSpecification
Object中存儲有關列的元數據,例如dataType,length,format等。
對於我的輸入文件中的幾千行,它可以正常工作,但是一旦行數開始增加,它就會由於內存問題(如預期的那樣)而開始崩潰。 因為它正在創建數百萬個具有數千個鍵的對象的地圖。
我知道這不是解決此類問題的有效解決方案。
因此,我擔心的是基於內存的解決方案是否可以在我的方案中工作,或者我必須更喜歡基於磁盤的解決方案,例如嵌入式DB或基於磁盤的Maps。
請告知我是否可以使用其他任何開源Map實現。
注意:對於文件解析和數據驗證,我使用的是hadoop,它在40個節點的集群上運行。
這是我的映射器的流程和實現:
接收值作為完整行,此后將其傳遞到Java框架,該框架將其轉換為相應的GenericObject(如上所述),然后將此對象傳遞給drools框架以進行進一步驗證。
映射器實現:
public void map(LongWritable key , Text value , Context context) throws IOException, InterruptedException {
//Convert the text value to string i.e line by line comes here
String record = value.toString();
// Develop a drools service that will take record as an input
// and will validate it on the basis of XL sheet provided
workingMemory = knowledgeBase.newStatefulKnowledgeSession();
DroolsObject recordObject = DroolsServiceImpl.validateByRecord(record, fileMetaData, workingMemory);
//Check to validate if the processed record
if(recordObject.isValid) {
context.getCounter(AppCounter.VALID_RECORD).increment(1);
mapperOutputKey.set("A");
mapperOutputValue.set(recordObject.toString());
context.write(mapperOutputKey,mapperOutputValue);
}
else {
context.getCounter(AppCounter.INVALID_RECORD).increment(1);
mapperOutputKey.set("R");
mapperOutputValue.set(recordObject.toStringWithErrors());
context.write(mapperOutputKey,mapperOutputValue);
}
}
由於必須將文件中每個字節的數據保存在內存中(可能的分隔符除外),因此首先要查看文件的大小並將其與內存大小進行比較。 如果您的文件大於內存,請抓緊將其保存在內存中的整個想法。
如果內存大於文件 ,則有機會,盡管您需要仔細檢查此文件將來可能如何增長,程序將在哪些平台上運行,等等。
因此, 假設它適合您,您的數據結構將更加高效。 一種簡單的節省內存的方法是抓取地圖,然后將每個記錄保存為字符串(以文件中的編碼)。 字符串數組應具有最小的開銷,盡管您需要確保在填充原始數組時不會不斷調整其大小。
在數據結構變大時保持數據結構簡單,可以節省大量內存。
另外,如果數據很容易裝入內存,則可能需要對JVM進行一些調整,以為其分配足夠的內存( 使用-Xmx更改堆大小)以使JVM足夠大。 我希望您在64位平台上使用64位JVM。
我建議將數據保留在一個( byte[][]
)表中,並通過其編號引用行。 然后,您可以使用游標按需讀取相應的字段:
class FieldSpecification {
private final int row;
private final byte[][] mem;
public String fieldName();
public String dataType();
public int length();
public String value();
public String format();
}
垃圾收集器應該很容易地處理這些對象。 您只需要關心他們的生命周期。
如果字節數組不適合您的內存,那么無論如何您都會被搞砸。
然后,您可以通過將名稱映射到行號來實現映射。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.