3

Web アプリケーションにキャッシュを作成したいと考えています。これにより、最上位層 (MVC) が、下位層 (サービスと DB) から取得した値を永続化して、不要な要求を回避できるようになります。キャッシュに保存したいデータは Web サイトのすべてのページで必要になるため、このキャッシュはリクエストの量を大幅に削減することを目的としています。アイデアは、多くのスレッドがコレクションからデータを読み取り、1 つのスレッドがそれをクリアして、キャッシュの有効期限が切れた後に新しいデータを取得するというものです。これは、コレクションが頻繁な読み取り操作とまれな書き込み操作に使用されることを意味します。

私にとっての問題は、これらの目的に適したクラスを選択することです。.NET 4 で導入されたからの同時実行クラスのセットについて読みました。またはSystem.Collections.Concurrentを使用する必要はまったくありませんが、とのいずれかを選択する必要があります。 ConcurrentQueueConcurrentStackBlockingCollectionConcurrentBagConcurrentDictionary

ConcurrentBagこの場合の最良の解決策のようです。しかし、私はこの記事でその並行辞書を読みました

...読み取り操作では完全にロックフリーです。このように、辞書からの読み取りが最も頻繁な操作であるシナリオに最適化されています。

おそらく最善の解決策は、ConcurrentDictionary<int, MyTypeOfObj>代わりに使用することですか?それとも、私は並行型をまったく必要とせず、単純Listに仕事をするのでしょうか? おそらく、キャッシュの更新時に操作をロックすることができれば、それでよいでしょう。しかし、 simple を使用することlockは望ましくありません。

アドバイスや説明をいただければ幸いです。

アップデート

キャッシュは、アウトレットのマップ ポイントを格納するために使用されます。アウトレットのセットは非常に安定していますが、それらを追加するための UI があるはずなので、挿入操作は非常にまれです。タイムアウト後に基になるレイヤーからコレクション全体を取得し、挿入操作を実行する方が簡単な場合があります。検索も必要ありません。読み取りは単純な列挙を意味します。

4

1 に答える 1

0

質問へのコメントに基づいて、使用することにしMemoryCacheました(実際、私はよく知りませんでした)。データ用に個別のキャッシュ インスタンスは必要ないため、Defaultプロパティに保持されているキャッシュを使用します。

必要でない限り、MemoryCache インスタンスを作成しないでください。(...) アプリケーションでキャッシュ インスタンスを 1 つだけ作成する場合は、デフォルト キャッシュを使用し、キャッシュにアクセスする必要があるときに Default プロパティからそのキャッシュへの参照を取得します。

リンク (MSDN)

次の方法で作成したキャッシュの初期化:

private static MemoryCache _instance = MemoryCache.Default;

public static IEnumerable<MyDto> GetDtos()
{
    var result = _instance.Get(SOME_NAME);
    if (result == null)
        result = InitializeCache();
    return result;
}

読み取り操作のロックはありません。InitializeCache次に、複数のリクエストを防ぐために 1 つのロックインを行います。

private static IEnumerable<MyDto> InitializeCache()
{
    lock (_monitor) // here all threads but one will stop
    {
        var result = _instance.Get(SOME_NAME); // in case this thread is not the first who entered the lock
        if (result == null)
        {
            result = RetrieveSomeHowYourDataFromDbOrService();
            if (result == null)
                return null; // or exception
            _instance.Set(SOME_NAME, result, new CacheItemPolicy { AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddSeconds(TIMEOUT)), RemovedCallback = CacheClearedCallback}); 
        }
        return (IEnumerable<MyDto>)result;
    }
}

を使用するCacheItemPolicyと、期限切れのアイテムをクリアしたり、コールバックからアイテムを再度取得したりできます。

private static void CacheClearedCallback(CacheEntryRemovedArguments arguments)
{
    InitializeCache();
}

この場合、キャッシュは消費者からの要求なしに更新されます (アプリケーションの最初の要求で行われるためではありません)。

おそらく、これはこれまでで最高の解決策ではありませんが、希望は誰かを助けるでしょう. ヒントとコメントをありがとう。

于 2014-06-08T17:48:12.770 に答える