私たちが実際に直面しているアーキテクチャの問題について質問したいと思います。
- 複数のサーバーに分散されたアプリケーションがあります
- activeMQ を介してデータを消費しています。
- 同期を維持する必要がある Price というオブジェクトがあります。
- このオブジェクトは複数回受け取ることができます。
- 価格には「lastUpdate」というフィールドがあり、最新の「lastUpdate」で価格を保存/更新する必要があります。
- 最後に受け取った価格の lastUpdate が以前のものより新しいという保証はありません。
すべてを同期させるには、3 つの方法があります (すべてを使用する必要があります)。
- 価格の非同期更新/挿入を受け取ることができます (リスナーを使用)
- 15 分ごとに、過去 15 分間に変更されたすべての価格を送信するようプロデューサーに依頼します (予定されたタスク)
- 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 秒 (平均 100,000 の価格を処理) したいのに、完了するのに時間がかかる (30/40 秒) ことです。私たちが使用しているロジックには、パフォーマンスを改善する方法がないようです。そのため、データの同期を維持する方法を変更する必要があると思います...何か提案はありますか?
編集:
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() のみをキーとして使用します。