2016-02-23 66 views
1

背景使用Spring批量讀取文件,並寫入地圖

我是相當新的Spring Batch的,並具有以下要求:

  1. 讀取一個文件的百萬記錄的minumum (CSV,管道分隔符等)
  2. 將文件中的每一行加載到一個Map with key作爲第一列,並將值作爲域對象/ POJO加載。

據我所知,Spring批處理有一種稱爲面向塊的處理,其中一個配置讀取器,處理器和一個寫入器來處理由commit-interval支配的一定數量的記錄。這可以進一步使用讀者的任務執行程序或通過分區添加另一層多線程進行擴展。

問題

如在2點以上解釋,我想我的文件加載到地圖。爲了討論的緣故,可以說我實現了下面的ItemWriter,它將塊聚合到一個Map中。

public class MapItemWriter implements ItemWriter<SomePOJO> { 

    private Map<String, SomePOJO> somePojoMap; 

    public MapItemWriter() { 
     System.out.println("Writer created "); 
     somePojoMap= new ConcurrentHashMap<String, SomePOJO>(); 
    } 

    public void write(List<? extends SomePOJO> item) throws Exception { 
     if (item != null && item.size() > 0) { 
      for (SomePOJO data : item) { 
       String uniqueId = data.Id(); 
       somePojoMap.put(uniqueId, data); 
      } 
     } 
    } 

    public Map<String, SomePojo> getSomePojoMap() { 
     return somePojoMap; 
    } 
} 

因爲我有機會到我的ItemWriter豆,我可以再打getSomePojoMap得到彙總圖在我的檔案記錄;然而,在ItemWriter中持有像這樣的Map並不覺得這是最好的方式。另一個問題是,使用ConcurrentHashMap可能會降低性能,但我沒有看到任何其他方式可以以線程安全的方式將文件聚合到Map中。

有沒有更好的方法來將我的文件聚合到一個Map中,而不是在我的writer中保存一個Map並使用ConcurrentHashMap?

+0

爲什麼要將數據加載到地圖中?地圖填充後會發生什麼? –

+0

@MichaelPralow我們有一個遺留系統,它將文件中的數據加載到一個Map中(每個文件一個)。我們想用Spring批次替換數據加載層。這些映射用於匯聚層,該匯聚層將來自不同映射的數據聚合爲在另一個系統偵聽的JMS隊列上發送的主對象。我們不想更改聚合層,因爲這意味着要修改整個遺留系統。我們希望提高數據加載性能。如果我們保持與匯聚層的接口相同,它可以繼續工作,就好像沒有任何變化。 – CKing

回答

1

或多或少。你可以做一些小的改進,比如把地圖放在一個單獨的bean中,這樣可以讓你爲writer bean和地圖創建不同的生命週期,並且也可以將地圖的讀者與作者分開。例如,你可以把地圖放在一個作業範圍的bean中,並且仍然讓作者成爲一個單例。

如果你的工作被劃分爲多個線程(我假設你不希望地圖在作業之間共享),那麼你只需要一個ConcurrentHashMap

+0

謝謝。你是對的。 「Map」不是跨作業共享的。另外,讀取文件的步驟將使用Tasklet與TaskExecutor,或者我甚至可以將文件分割爲磁盤上的物理分區。我的工作的最終結果將是包含文件內容的地圖。我的工作只有一個步驟,即讀取文件並加載到「Map」。我在互聯網上遇到的大多數例子都使用作者寫入文件或數據庫。我覺得我正在使用ItemWriter來處理它沒有設計的東西。 Spring Batch的用戶會對此產生不滿嗎? – CKing

+0

@CKing我不知道我是否可以爲一位資深的Spring Batch用戶發言;我可以說,你並沒有使用Spring Batch分塊步驟的設計目的:可以一次一個事務地處理大塊數據,並可選擇重試,跳過和重新啓動。只要將以前的塊保存在內存中,並且您的作者的操作不能回滾,則無法一次有效地處理塊。但第一個特點似乎是由於您的遺留要求,第二個特點可能並不是真的,因爲您的作家永遠不會失敗。 – Artefacto

+0

這正是我的擔心。使用框架來實現它不是爲了設計的。我的要求不適合典型的Spring批處理用例。我主要是選擇Spring批處理,因爲它是現成的平面文件解析API和縮放選項。如果我的數據集將來會增加(通常會發生這種情況),那麼我可以使用Spring批處理提供的各種選項來擴展我的應用程序。如果讀取可伸縮性是我唯一的目標,您是否知道我應該關注的其他框架? – CKing

0

爲什麼不使用File Item Writer。

我假設這張地圖應該寫入一個文件。可能是一個平面文件(txt)

如果是這種情況,請嘗試使用FlatFileItemWriter。如果您需要將這些數據寫入xml文件,您可以使用StaxEventItemWriter

即使您不需要將數據寫入文件(在批處理結束時只需要映射)。我認爲將數據寫入文件並在之後從文件中讀取整個地圖將會「更便宜」。將作圖保存在作業範圍內意味着該對象將在每個塊中保留在db中,並且將在每個塊上從db中檢索,這相當昂貴的操作。

+0

如果我將數據從文件加載到'Map'中,然後將其寫回到文件中,然後在需要時再次將其加載到Map中,我是不是會繞圈轉圈? – CKing

+0

如果你對提取的數據沒有邏輯,我認爲你不會享受閱讀塊效益。仍然春天批次有更多的功能(重試,聽衆等),但讀取卡盤和保存地圖爲作業範圍對象將是昂貴的,不值得。 –

+0

我給了它一些想法,你說的是正確的。如果我只是將數據加載到「Map」中,則讀入塊沒有任何好處;然而,事實並非如此。我將對這些數據應用一些過濾器,並刪除那些不符合過濾條件的記錄。就像一個數據庫 - where子句。 – CKing