web-dev-qa-db-ja.com

MemoryCacheの複数のインスタンスを使用する

System.Runtime.Caching名前空間を使用してアプリケーションにキャッシング機能を追加したいのですが、おそらくいくつかの場所と異なるコンテキストでキャッシングを使用したいと思うでしょう。そのためには、いくつかのMemoryCacheインスタンスを使用します。

しかし、 here を参照してください。MemoryCacheの複数のインスタンスを使用することはお勧めできません。

MemoryCacheはシングルトンではありませんが、少数または潜在的に1つのMemoryCacheインスタンスのみを作成し、アイテムをキャッシュするコードはそれらのインスタンスを使用する必要があります。

複数のMemoryCacheインスタンスはアプリケーションにどのように影響しますか?アプリケーションで複数のキャッシュを使用することは非常に一般的なシナリオのように思えるので、この種の奇妙なことに気付きます。

EDIT:より具体的には、各インスタンスのキャッシュを保持するクラスがあります。 MemoryCacheの使用を避け、別のキャッシュソリューションを探す必要がありますか?この状況でMemoryCacheを使用しているのは悪いと考えられていますか?

67
Adi Lester

私自身も最近これを経験しました。インメモリキャッシュはプロセス固有である(ウェブサイト、ネイティブビジネスアプリ、または複数のサーバーの複数のインスタンス間で共有されない)ことを考慮すると、コードの編成上の理由(他の方法で達成できる)を除いて、複数のMemoryCacheインスタンスを持つことは実際にはメリットがありません。

メモリキャッシュは、主にメモリ管理機能のために単独で使用することを目的としています。 (ある程度オーバーヘッドがある)パフォーマンスカウンターに加えて、MemoryCacheは割り当てられたメモリを使い果たすとアイテムを期限切れにすることもできます。

キャッシュの現在のインスタンスがCacheMemoryLimitプロパティで設定されたメモリの制限を超えた場合、キャッシュ実装はキャッシュエントリを削除します。アプリケーションの各キャッシュインスタンスは、CacheMemoryLimitプロパティで指定されたメモリ量を使用できます。

from MemoryCache.CacheMemoryLimitプロパティ

MemoryCacheのインスタンスを1つだけ使用することにより、このメモリ管理をアプリケーションインスタンス全体に効率的に適用できます。アプリケーション全体で最も重要でない項目を期限切れにします。これにより、ハードウェアの能力を超えることなく、最大限のメモリ使用が保証されます。 1つのMemoryCache(クラスの1つのインスタンスなど)のスコープを制限すると、アプリケーションのメモリを効果的に管理できなくなります(すべてを「見る」ことができないため)。これらのキャッシュがすべて「ビジー」である場合、メモリの管理に苦労する可能性があり、ほぼ同じ効率になることはありません。

これは、専用サーバーの豪華さを持たないアプリケーションでは特に重要です。 150mb RAM(一般的な安価な$ 10 /月ホスティング)のみが割り当てられている共有サーバーでアプリを実行している場合を想像してください。このメモリ使用量を超えると、アプリプールがリサイクルされ、メモリキャッシュ内のアプリがすべて失われます!(一般的な安価なホスティングプラクティス)同じことが、共有企業サーバーの社内でホストされる非Webアプリにも当てはまります。取引では、そのマシンのすべてのメモリを独占しないで、他のビジネスアプリケーションと平和的に共存するように言われます。

メモリ制限、アプリプールのリサイクル、キャッシュの喪失は、Webアプリによくある「アキレス腱」です。アプリが最もビジーな場合、メモリ割り当てを超過し、すべてのキャッシュエントリが失われるため、最も頻繁にリセットされます。そのため、最初にキャッシュされるはずだったものを再取得します。アプリが意味することは、実際に最大負荷でパフォーマンスを失うことではありません。

MemoryCacheはSystem.Web.Caching.Cache実装のWeb固有ではないバージョンですが、これはキャッシュ実装の背後にあるロジックを示しています。ハードウェアを排他的に使用していない場合、同じロジックを非Webプロジェクトに適用できます。キャッシュがマシンにページファイルのスワップを強制的に開始させた場合、キャッシュはディスク上のキャッシュよりも高速ではなくなります。その制限が2 GBか何かであっても、常にどこかに制限が必要です。

私の場合、これについて読んだ後、アプリで1つの「public static MemoryCache」を使用するように切り替え、キャッシュキーによってキャッシュされたアイテムを分離しました。たとえば、インスタンスごとにキャッシュする場合、「instance- {instanceId} -resourceName- {resourceId}」のようなキャッシュキーを使用できます。キャッシュエントリの名前の間隔と考えてください。

お役に立てば幸いです!

65
BenSwayne

私もいくつか使用します。通常、タイプごとに1つ。

MemoryCacheを見ると、AppDomainイベントにフックし、パフォーマンスカウンターを維持していることがわかります。それから、複数のリソース(CPU、カウンター、メモリなど)を使用することで、リソースの面でオーバーヘッドが発生するのではないかと思います。

6
Kit