web-dev-qa-db-ja.com

AppFabricキャッシング-DataCacheFactoryとDataCacheの適切な使用

私は、AppFabricキャッシング呼び出し用のデータキャッシュとデータキャッシュファクトリの使用を調整するための最もパフォーマンスの高い方法を探しています。単一の静的DataCacheFactory(またはラウンドロビン設定でいくつか)を使用するのが道のりのようです。

すべてのDataCacheオブジェクトリクエストに対してGetCache( "cacheName")を呼び出すのですか、それともDataCacheファクトリの初期化時に1つを静的にして、それをすべての呼び出しに使用するのですか?

例外を処理し、失敗コードを確認して、再試行する必要がありますか?

複数のスレッドがキャッシュストアを使用しようとして、同じアイテムを(キーで)必要とする場合、競合を考慮する必要がありますか?

これの設計と使用法を適切に調査するある種のドキュメントはありますか?


フォーラムからこれまでに収集したいくつかの情報:

http://social.msdn.Microsoft.com/Forums/en-AU/velocity/thread/98d4f00d-3a1b-4d7c-88ba-384d3d5da915

「ファクトリの作成にはクラスタへの接続が含まれ、時間がかかる場合があります。ただし、使用するファクトリオブジェクトとキャッシュを取得したら、それらのオブジェクトを再利用してキャッシュに入れたり入れたりすることができます。はるかに高速なパフォーマンスをご覧ください。」

http://social.msdn.Microsoft.com/Forums/en-US/velocity/thread/0c1d7ce2-4c1b-4c63-b525-5d8f98bb8a49

「単一のDataCacheFactory(シングルトン)を作成すると、複数のDataCacheFactoryを作成するよりもパフォーマンスが向上します。呼び出しごとにDataCacheFactoryを作成しないでください。パフォーマンスが低下します。」

「ラウンドロビンアルゴリズム(ファクトリインスタンスが3/4/5)をシングルトンにカプセル化して、負荷テストの結果を比較してみてください。」

http://blogs.msdn.com/b/velocity/archive/2009/04/15/pushing-client-performance.aspx

「クライアントの数を増やしてキャッシュスループットを上げることができます。ただし、クライアントのセットを減らしてスループットを上げたい場合は、複数のDataCacheFactoryインスタンスを使用するのがコツです。DataCacheFactoryインスタンスはサーバーへの接続を作成します(例:たとえば、サーバーが3つある場合は、3つの接続が作成され、データキャッシュからこれらの接続へのすべてのリクエストが多重化されます。したがって、put/getの量が非常に多い場合、これらのTCP接続はボトルネックになります。したがって、1つの方法は、複数のDataCacheFactoryインスタンスを作成し、それらに対して操作を使用することです。」


ここでこれまでに使用されているもの...プロパティが呼び出され、戻り値がnullでない場合、操作が実行されます。

private static DataCache Cache
{
    get
    {
        if (_cacheFactory == null)
        {
            lock (Sync)
            {
                if (_cacheFactory == null)
                {
                    try
                    {
                        _cacheFactory = new DataCacheFactory();
                    }
                    catch (DataCacheException ex)
                    {
                        if (_logger != null)
                        {
                            _logger.LogError(ex.Message, ex);
                        }
                    }
                }
            }
        }

        DataCache cache = null;

        if (_cacheFactory != null)
        {
            cache = _cacheFactory.GetCache(_cacheName);
        }

        return cache;
    }
}

Microsoft AppFabricフォーラムでこの質問を参照してください: http://social.msdn.Microsoft.com/Forums/en-AU/velocity/thread/e0a0c6fb-df4e-499f-a023-ba16afb6614f

33
CRice

フォーラムの投稿からの回答は次のとおりです。

こんにちは。返信が遅れて申し訳ありませんが、これらは素晴らしい質問であり、おそらく他の人にも役立つと思います。

異なる構成が必要な場合を除いて、スレッドごとに複数のDataCacheFactoryが必要になることはありません。たとえば、DataCacheFactoryConfigurationクラスを使用してDataCacheFactoryをプログラムで構成する場合、ローカルキャッシュが有効になっているクラスと有効になっていないクラスを作成できます。この場合、シナリオに必要な構成に応じて、異なるDataCacheFactoryオブジェクトを使用します。ただし、構成の違いを除いて、複数のDataCacheFactoriesを作成してもパフォーマンスが向上することはありません。

同じ件名で、MaxConnectionsToServer設定があります(DataCacheFactoryConfigurationまたはdataCacheClient要素の属性としてのアプリケーション構成ファイルのプログラムによる)。これにより、キャッシュクラスターに対して開かれるDataCacheFactoryごとのチャネルの数が決まります。高いスループット要件があり、CPU /ネットワーク帯域幅も利用できる場合は、この設定を3以上に増やすと、スループットを上げることができます。これを理由なく、またはニーズに対して高すぎる値に増やすことはお勧めしません。値を変更してからシナリオをテストして、結果を観察する必要があります。将来的には、これについてより公式なガイダンスが得られることを望んでいます。

DataCacheFactoryを取得したら、複数のDataCacheオブジェクトを取得するためにGetCache()を複数回呼び出す必要はありません。同じファクトリの同じキャッシュに対してGetCache()を呼び出すたびに、同じDataCacheオブジェクトが返されます。また、DataCacheオブジェクトを取得したら、DataCacheFactoryを引き続き呼び出す必要はありません。 DataCacheオブジェクトを保存して、引き続き使用してください。ただし、DataCacheFactoryオブジェクトを破棄しないでください。 DataCacheオブジェクトの寿命は、DataCacheFactoryオブジェクトに関連付けられています。

Getリクエストとの競合について心配する必要はありません。ただし、Put/Addリクエストでは、複数のデータキャッシュクライアントが同じキーを同時に更新している場合に競合が発生する可能性があります。この場合、エラーコードERRCA0017、RetryLater、およびサブステータスES0005、KeyLatchedで例外が発生します。ただし、例外処理と再試行ロジックを簡単に追加して、このようなエラーが発生したときに更新を再試行できます。これは、さまざまなサブステータス値を持つRetryLaterコードに対して実行できます。詳細については、 http://msdn.Microsoft.com/en-us/library/ff637738.aspx を参照してください。 GetAndLock()およびPutAndUnlock()APIを使用して、ペシミスティックロックを使用することもできます。この方法を使用する場合は、すべてのキャッシュクライアントがペシミスティックロックを使用していることを確認する必要があります。 Put()呼び出しは、以前にGetAndLock()によってロックされていたオブジェクトを一掃します。

これがお役に立てば幸いです。私が言ったように、私たちはこの種のガイダンスをすぐにいくつかの正式なコンテンツに取り入れたいと思っています。ただし、それまではフォーラムで共有することをお勧めします。ありがとう!

ジェイソン・ロス

15
CRice

すべてのDataCacheオブジェクトリクエストに対してGetCache( "cacheName")を呼び出すのですか、それともDataCacheファクトリの初期化時に1つを静的にして、それをすべての呼び出しに使用するのですか?

私は本当に答えはそうあるべきだと思います。両方の方法を試して、違いがあるかどうかを確認してください。ただし、1つの静的DataCacheは、Getを呼び出すたびに対応するGetCacheを呼び出すよりも理にかなっているようです。

その「クライアントパフォーマンスの向上」の記事は、DataCacheFactoryインスタンスの数が最大のパフォーマンスを実現し、それを超えるとメモリオーバーヘッドが機能し始めるスイートスポットがあることを示唆しています-ガイドライン(または経験則)を提供しなかったのは残念です)このスポットがどこにあるか。

パフォーマンスを最大化するためのドキュメントはありません。AppFabricはまだ新しすぎて、これらのガイドラインをまだ揺るがすことができないと思います。 Pro AppFabric book のコンテンツを確認しましたが、一般的には、キャッシュ(Velocity)の部分よりも、AppFabricのワークフロー(Dublin)側に関係しているようです。

ただし、「チャンキー」オブジェクトをキャッシュして、Getへの呼び出しを減らす可能性はありますか?個々のオブジェクトではなくコレクションをキャッシュしてから、クライアントでコレクションを解凍できますか?ページの読み込みごとに700のキャッシュを取得するのは、膨大な数のようです。

4
PhilPursglove