2015-11-07 62 views
0

我想問你一個關於實際上我們正面臨的架構問題的問題。批量更新和單個異步更新與Java,分佈式應用程序

  • 我們在多個服務器
  • 我們通過ActiveMQ的消費數據的分佈式應用程序。
  • 我們有一個名爲Price的對象,需要保持同步。
  • 這個對象可以被多次接收。
  • 價格有一個名爲「lastUpdate」的字段,我們需要使用最近的「lastUpdate」存儲/更新價格。
  • 不保證最近收到的價格具有上次更新的最後更新日期。

保持同步的一切,我們有3種方式(我們必須使用所有的)

  • 我們可以接受的價格的異步更新/插入(使用偵聽)
  • 每15分鐘我們將要求生產者發送給我們大家,在過去的15分鐘(scheduledTask)
  • 每1小時我們更新所有的價格(schduledTask)
被更改價格

TECNOLOGIES使用:

  • 的ActiveMQ作爲總線
  • Hazelcast爲distribuited地圖在插入前syncronize
  • JPA

現在工作原理: 每次異步價格添加/更新到達我們執行:

這就是我們正在做的每個價格,我們想要更新/堅持(單一和批量更新/插入方法OD稱此一個)

private void priceAddedOrUpdated(Price retrievedPrice) 
{ 
    Date dateInTheMap = hazelcastPriceMap.get(retrievedPrice.getId()); 
    if(retrievedPrice.getLastUpdate>dateInTheMap(
    { 
     //doInTransacion 
     try{ 
      hazelcastPriceMap.lock(retrievedPrice.getId()) 
      //do some logic including 
      persist the price 
      hazelcastPriceMap.put(retrievedPrice.getId(),retrievedPrice.getLastUpdate()) 
     } 
     finally{ 
      //release the lock 
     } 
    } 
} 

的問題是,它需要的工作年齡(30/40秒)來完成的,而我們要做的是在4/5秒(處理10萬種價格的平均值)。 我們正在使用的邏輯似乎沒有任何方法來提高性能。所以我認爲我們需要改變保持數據同步的方式......任何建議?

編輯:

pveentjer的建議下我擴展了EntryProcessor類,使人們有可能通過價格在構造函數中被更新的地圖:

public class PriceEntryProcessor implements EntryProcessor, EntryBackupProcessor, Serializable { 

    Map<Long, Price> priceMap; 

    public PriceEntryProcessor(Map<Long, Price> priceMap) 
    { 
     super(); 
     this.priceMap = priceMap; 
    } 
    public Object process(Map.Entry entry) 
    {//get the price from the map for the entry and do the logic/db insertion 

}

我在EntryProcessor中我們只能發送關鍵字的值。但是我們只使用price.getId()作爲關鍵字。

+0

您是否測量性能以找到熱點? – Kayaman

回答

0

一個潛在的加速可能是使用EntryProcessor。

在EntryProcessor中,您可以免費獲得鎖定,因爲您可以保證沒有其他進程在同一分區中運行。數據庫邏輯也可以移入EntryProcessor。這會將遠程處理減少一半。

你在做任何配料嗎?因爲這可能會造成巨大的差異。因此,對於單個分區的批處理(如100次更改),一旦收到,就利用入口處理器一次處理整個批次。

沒有配料,你將有100 x(1鎖,1解鎖,1獲得,1放)= 400 ops。批量爲100時,您將有1個遠程操作。所以這是400倍(忽略複製)。

+0

謝謝pveentjer!我正在閱讀EntryProcessor.Indeed的教程,它將加快我們的更新遠程一半! – user1974059

+0

也想想批量。批次可以對性能產生巨大影響。 – pveentjer

+0

在我們的共享映射中,我們僅存儲priceId(鍵),lastUpdate(值)。我們這樣做是爲了避免在內存中存儲太多對象。因此,解決方案可能是:創建可擴展EntryProcessor並具有字段地圖的EntryProcessorPrice。創建一個實例,以必須處理的價格傳遞地圖.call executeOnEntries將執行僅更新地圖中包含的價格。 – user1974059