使用Java,分发应用程序进行批量更新和单一异步更新

时间:2015-11-07 13:05:28

标签: java performance jpa sql-update hazelcast-imap

我想问你一个关于我们实际面临的架构问题的问题。

  • 我们有一个分布在多个服务器上的应用程序
  • 我们通过activeMQ消费数据。
  • 我们有一个名为Price的对象,需要保持同步。
  • 此对象可以多次接收。
  • Price有一个名为“lastUpdate”的字段,我们需要使用最新的“lastUpdate”存储/更新Price。
  • 没有保证最后收到的价格的lastUpdate比之前的更新。

为了使所有内容保持同步,我们有3种方式(我们必须使用所有方法)

  • 我们可以收到价格的异步更新/插入(使用监听器)
  • 我们会每15分钟要求生产商向我们发送过去15分钟内已更改的所有价格(scheduledTask)
  • 我们每1小时更新所有价格(schduledTask)

使用的技术:

  • ActiveMQ作为总线
  • Hazelcast作为在插入前同步的分布式地图
  • JPA

现在如何运作: 每次添加/更新异步价格时,我们都会执行:

这就是我们要为每个我们想要更新/持久的价格做的事情(单个和批量更新/插入方法都调用这个)

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
        }
    }
}

问题在于,我们希望在4/5秒内完成任务需要很长时间(30/40秒)(处理平均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()作为密钥。

1 个答案:

答案 0 :(得分:0)

一个潜在的加速可能是使用EntryProcessor。

在EntryProcessor中,您可以免费获得锁定,因为您可以保证在同一分区中没有其他进程在运行。您也可以将db逻辑移入EntryProcessor。这会将遥控减少一半。

你在进行任何批处理吗?因为这可能会产生巨大的巨大差异。因此,对于单个分区进行100次更改的批处理,一旦收到它们,就可以使用入口处理器一次性处理整个批处理。

如果没有批处理,你将有100 x(1次锁定,1次解锁,1次获取,1次放置)= 400次操作。批量为100时,您将拥有1个远程操作。所以这少了400倍(忽略复制)。