0

私たちが実際に直面しているアーキテクチャの問題について質問したいと思います。

  • 複数のサーバーに分散されたアプリケーションがあります
  • 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() のみをキーとして使用します。

4

1 に答える 1

0

EntryProcessor を利用することで、スピードアップできる可能性があります。

EntryProcessor では、同じパーティションで他のプロセスが実行されていないことが保証されるため、無料でロックを取得できます。db ロジックも EntryProcessor に移動します。これにより、リモート処理が半分に削減されます。

バッチ処理を行っていますか?これは非常に大きな違いを生む可能性があるからです。したがって、1 つのパーティションに対して 100 の変更をバッチ処理します。変更を受信したら、エントリ プロセッサを使用して、このバッチ全体を 1 回で処理します。

バッチ処理がなければ、100 x (1 ロック、1 ロック解除、1 get、1 put)=400 オペレーションになります。100 のバッチ処理では、1 つのリモート オペレーションがあります。つまり、400 分の 1 です (複製を無視します)。

于 2015-11-08T07:53:43.460 に答える