web-dev-qa-db-ja.com

System.Runtime.Caching.MemoryCacheとHttpRuntime.Cache-違いはありますか?

MemoryCacheHttpRuntime.Cacheに違いがあるのではないかと思っています。ASP.NETMVCプロジェクトではどちらが好ましいですか?

私が理解している限り、両方ともスレッドセーフであり、APIは一見してほぼ同じであるため、どちらを使用するかについて違いはありますか?

83
Giedrius

HttpRuntime.Cache は、現在のアプリケーションの Cache を取得します。

MemoryCache クラスは、ASP.NET Cacheクラスに似ています。

MemoryCacheクラスには、キャッシュにアクセスするための多くのプロパティとメソッドがあり、ASP.NET Cacheクラスを使用したことがある場合は使い慣れています。

HttpRuntime.CacheMemoryCacheの主な違いは、後者がASP.NETアプリケーションではない.NET Frameworkアプリケーションで使用できるように変更されていることです。

さらに読むには:

更新:

ユーザーのフィードバックによると、ジョン・デイビスのブログが機能していない場合があります。そのため、記事全体を画像として掲載しています。ご覧ください。

注:はっきりしない場合は、画像をクリックしてください。その後、ブラウザで開きます。それからもう一度クリックしてズームします:)

enter image description here

78
Sampath

こちらがジョン・デイビスの記事です。読みやすさを保つために、現在は廃止されたEntLibセクション、イントロ、および結論を省略します。


ASP.NETキャッシュ

ASP.NET、またはSystem.Web.dllアセンブリには、キャッシュメカニズムがあります。 Webコンテキストの外部で使用することを意図していませんでしたが、Webの外部で使用することができ、上記のすべての有効期限動作を一種のハッシュテーブルで実行します。

Googleを精査した後、.NETの組み込みキャッシュ機能について議論した多くの人々が、Web以外のプロジェクトでASP.NETキャッシュを使用することに頼ったようです。これは、.NETで最も利用可能で最もサポートされている組み込みキャッシュシステムではなくなりました。 .NET 4には、後で説明するObjectCacheがあります。 Microsoftは、ASP.NETキャッシュがWeb外での使用を目的としていないことを常に強く主張してきました。しかし、多くの人々はまだ.NET 2.0と.NET 3.5にとどまっており、何かを使用する必要があります。MSDNの明確な発言にもかかわらず、これはたまたま多くの人々に有効です。

注:Cacheクラスは、ASP.NETアプリケーションの外部で使用するためのものではありません。 Webアプリケーションにキャッシュを提供するために、ASP.NETで使用するために設計およびテストされました。コンソールアプリケーションやWindowsフォームアプリケーションなど、他の種類のアプリケーションでは、ASP.NETキャッシュが正しく機能しない場合があります。

ASP.NETキャッシュのクラスは、System.Web.dllのSystem.Web.Caching.Cacheです。ただし、単にCacheオブジェクトを更新することはできません。 System.Web.HttpRuntime.Cacheから取得する必要があります。

Cache cache = System.Web.HttpRuntime.Cache;

ASP.NETキャッシュの操作については、MSDN here で説明されています。

長所:

  1. ビルトインです。
  2. .NET 1.0の構文にもかかわらず、かなりsimpleを使用します。
  3. Webコンテキストで使用する場合、十分にテスト済みです。 Googleの検索によると、ウェブコンテキスト以外では、.NET 2.0以降を使用している限り、Microsoftが推奨しないにもかかわらず、問題を引き起こすことは一般に知られていません。
  4. notifiedは、アイテムが削除されたときにデリゲート経由で実行できます。これは、アイテムを存続させる必要があり、アイテムの優先度を事前に設定できなかった場合に必要です。
  5. この記事の上部にある削除方法のリストにある(a)、(b)、または(c)有効期限と削除のいずれかの方法の[個々のアイテムには柔軟性があります。有効期限の動作を物理ファイルの存在に関連付けることもできます。

短所:

  1. 静的であるだけでなく、1つしかない。 Cacheの独自の静的インスタンスを使用して独自のタイプを作成することはできません。アプリ全体の期間は1つのみです。キーに事前注入プレフィックスなどの処理を行う独自のラッパーでバケットをラップし、キー/値のペアを引き出したときにこれらのプレフィックスを削除できます。ただし、バケットは1つしかありません。すべてがひとまとめにされています。たとえば、3種類または4種類の異なるデータを個別にキャッシュする必要があるサービスがある場合、これは非常に厄介な場合があります。これは哀れなほど単純なプロジェクトにとって大きな問題ではないはずです。しかし、プロジェクトがその要件のためにかなりの複雑さを持っている場合、ASP.NETキャッシュは通常十分ではありません。
  2. アイテムは消えることがあります、willy-nilly。このキャッシュの実装に関する知識を更新するまで、多くの人はこれを認識していませんでした。既定では、ASP.NETキャッシュは、アイテムが「感じた」ときにアイテムを破棄するように設計されています。より具体的には、この記事の上部にあるキャッシュテーブルの定義の(c)を参照してください。同じプロセス内の別のスレッドがまったく異なる何かを処理しており、優先度の高いアイテムをキャッシュにダンプしている場合、.NETがメモリを必要とすると判断するとすぐに、キャッシュ内のいくつかのアイテムを破棄し始めますそれらの優先順位、低い優先順位が最初です。キャッシュアイテムを追加するためにここに記載されているすべての例では、メモリをクリアする目的で削除されないようにするNotRemovable優先度値ではなく、デフォルトの優先度を使用します。キャッシュ呼び出しでのCacheItemPriority.NotRemovableのペッパーリングは面倒な場合があります。そうでない場合はラッパーが必要です。
  3. キーは文字列でなければなりません。たとえば、レコードがロングまたは整数にキー付けされているデータレコードをキャッシュする場合、最初にキーを文字列に変換する必要があります。
  4. 構文は古くなっています。 .NET 1.0構文であり、ArrayListやHashtableよりもtableいです。ここにはジェネリックはなく、IDictionary <>インターフェースもありません。 Contains()メソッド、Keysコレクション、標準イベントはありません。 Get()メソッドと、Get()と同じことを行うインデクサーだけがあり、一致しない場合はnullを返し、Add()、Insert()(冗長?)、Remove()、GetEnumerator() 。
  5. DRY原則を無視デフォルトの有効期限/削除動作を設定して、それらを忘れることができるようにします。追加するアイテムを追加するたびに、追加するアイテムの有効期限または削除方法をキャッシュに明示的に指定する必要があります。
  6. キャッシュの詳細にアクセスする方法はありませんキャッシュされたアイテムの追加時のタイムスタンプなど。ここではカプセル化が少し行き過ぎたため、キャッシュされたアイテムを別のキャッシュメカニズム(セッションコレクションなど)に対して無効にする必要があるかどうかをコードで判断しようとすると、キャッシュの使用が難しくなります。
  7. 削除イベントはイベントとして公開されないため、追加時に追跡する必要があります。
  8. そして、私がそれを十分に言っていない場合、 Microsoftは明示的にそれを推奨します ウェブの外部で。 。NET 1.1では、安定性に自信を持って使用することは想定されていません Webの外部で呪われているので、気にしないでください。

.NET 4.0のObjectCache/MemoryCache

Microsoftはついに、最新バージョンの.NET Frameworkに抽象ObjectCacheクラスを実装し、Web以外の設定でメモリ内の目的でObjectCacheを継承および実装するMemoryCache実装を実装しました。

System.Runtime.Caching.ObjectCacheはSystem.Runtime.Caching.dllアセンブリにあります。これは、ASP.NETキャッシュにある基本的に同じ.NET 1.0スタイルのインターフェイスを宣言する抽象クラスです。 System.Runtime.Caching.MemoryCacheはObjectCacheのメモリ内実装であり、ASP.NETキャッシュに非常に似ていますが、いくつかの変更があります。

有効期限がスライドするアイテムを追加するには、コードは次のようになります。

var config = new NameValueCollection();  
var cache = new MemoryCache("myMemCache", config);  
cache.Add(new CacheItem("a", "b"),  
    new CacheItemPolicy  
    {  
        Priority = CacheItemPriority.NotRemovable,  
        SlidingExpiration=TimeSpan.FromMinutes(30)  
    }); 

長所:

  1. これはビルトインであり、現在はマイクロソフトがウェブ外でサポートおよび推奨しています。
  2. ASP.NETキャッシュとは異なり、MemoryCacheオブジェクトインスタンスをインスタンス化できます。

    注:静的である必要はありませんが、 Microsoftの推奨(黄色の注意を参照) である必要があります。

  3. ASP.NETキャッシュのインターフェイスに対して、いくつかのわずかな改善が行われました。たとえば、アイテムが追加されたときに、そこにいなくても削除イベントをサブスクライブできる機能、冗長なInsert()が削除され、アイテムはCacheItemで追加できますキャッシュ戦略を定義するイニシャライザを持つオブジェクト、およびContains()が追加されました。

短所:

  1. それでもDRYを完全に強化するわけではありません。私のわずかな経験から、スライド式の有効期限TimeSpanを一度設定して忘れることはできません。そして率直に言って、上記のアイテム追加サンプルのポリシーは読みやすくなっていますが、恐ろしい冗長性が必要です。
  2. まだ汎用キーではありません。キーとして文字列が必要です。したがって、データレコードをキャッシュしている場合、文字列に変換しない限り、longまたはintとして保存できません。

DIY:自分で構築する

明示的またはスライド式の有効期限を実行するキャッシュ辞書を作成するのは実際には非常に簡単です。 (メモリを消去するためにアイテムを自動削除する場合は、さらに難しくなります。)必要な作業は次のとおりです。

  1. タイプTの値、値がキャッシュに追加されたときに保存するDateTimeタイプのTimeStampプロパティ、およびタイムスタンプからどれだけ離れているかを示すTimeSpanを含むExpiringまたはExpirableなどの値コンテナクラスを作成します。アイテムの有効期限が切れます。明示的な有効期限については、タイムスタンプを引いた日付を指定してTimeSpanを設定するプロパティセッターを公開するだけです。
  2. クラスを作成し、IDictionaryを実装するExpirableItemsDictionaryと呼びましょう。コンシューマーによって定義された汎用クラスにすることを好みます。
  3. #2で作成したクラスで、Dictionary>をプロパティとして追加し、InnerDictionaryと呼びます。
  4. #2で作成されたクラスのIDictionaryの実装は、InnerDictionaryを使用してキャッシュされたアイテムを保存する必要があります。カプセル化により、上記の#1で作成されたタイプのインスタンスを介してキャッシュメソッドの詳細が非表示になります。
  5. インデクサー(this [])、ContainsKey()などが、値を返す前に期限切れのアイテムをクリアし、期限切れのアイテムを削除するように注意してください。アイテムが削除された場合、ゲッターでnullを返します。
  6. すべてのゲッター、セッター、ContainsKey()で、特に期限切れのアイテムをクリアするときに、スレッドロックを使用します。
  7. 有効期限が切れてアイテムが削除されるたびにイベントを発生させます。
  8. System.Threading.Timerインスタンスを追加し、初期化中にリグして、15秒ごとに期限切れのアイテムを自動削除します。これは、ASP.NETキャッシュと同じ動作です。
  9. 既に存在する場合、アイテムのコンテナ(期限切れインスタンス)のタイムスタンプを置き換えることにより、スライド式の有効期限をプッシュするAddOrUpdate()ルーチンを追加することができます。

マイクロソフトは、ユーザーベースが依存関係を構築しているため、元の設計をサポートする必要がありますが、それは、それらが優れた設計であることを意味しません。

長所:

  1. 実装に対して完全な制御があります。
  2. DRYを強化デフォルトのキャッシュ動作を設定し、アイテムを追加するたびにキャッシュの詳細を宣言せずにキー/値のペアをドロップするだけです。
  3. モダンインターフェイス、つまりIDictionary<K,T>を実装できます。これにより、インターフェイスが辞書インターフェイスとしてより予測しやすくなり、IDictionary <>で動作するヘルパーおよび拡張メソッドからアクセスしやすくなるため、消費がはるかに容易になります。
  4. キャッシュの詳細をカプセル化しない。読み取り専用のパブリックプロパティを介してInnerDictionaryを公開し、キャッシュ戦略に対して明示的な単体テストを記述したり、基本的なキャッシュ実装を追加のキャッシュ戦略で拡張したりできますその上に構築します。
  5. ASP.NETキャッシュまたはキャッシュアプ​​リケーションブロックの.NET 1.0スタイルの構文に既に慣れている人にとっては、必ずしも使い慣れたインターフェイスではありませんが、インターフェイスを定義できます見てほしい。
  6. キーに任意のタイプを使用できます。これがジェネリックが作成された理由の1つです。すべてが文字列でキー設定されるべきではありません。

短所:

  1. Microsoftによって発明されたものでも、Microsoftによって承認されたものでもないなので、同じ品質保証はありません。
  2. 上記の命令のみが実装されていると仮定すると、優先度に基づいてメモリをクリアするための項目を「意志的に」クリアしません(とにかくキャッシュのコーナーケースユーティリティ関数です.. BUY RAMここでキャッシュを使用している場合、RAMは安価です)。

これらの4つのオプションすべての中で、これが私の好みです。この基本的なキャッシュソリューションを実装しました。これまでのところ、それは完全に動作しているようで、既知のバグはありません(下のコメントまたはjon-at-jondavisにコメントがある場合は私に連絡してください!!)、私はそれを必要とする私の小さなサイドプロジェクトのすべてでそれを使用するつもりです基本的なキャッシュ。ここにあります:

Githubリンク: https://github.com/kroimon/ExpirableItemDictionary

古いリンク: ExpirableItemDictionary.Zip

価値のある言及:AppFabric、NoSQL、その他

このブログ記事のタイトルは、「Heavy-Duty Caching」ではなく「Simple Caching」を示していることに注意してください。頑丈なものを使いたい場合は、専用のスケールアウトソリューションを検討する必要があります。

22
DeepSpace101

MemoryCacheは、それが言うとおり、memoryに保存されたキャッシュです

HttpRuntime.Cache(「 http://msdn.Microsoft.com/en-us/library/system.web.httpruntime.cache(v = vs.100).aspx および http ://msdn.Microsoft.com/en-us/library/system.web.caching.cache.aspx )は、アプリケーションで設定したものすべてに永続化します。

たとえば、「ASP.NET 4.0:カスタム出力キャッシュプロバイダーの作成」を参照してください http://weblogs.asp.net/gunnarpeipman/archive/2009/11/19/asp-net-4-0-writing-custom -output-cache-providers.aspx

3