2012-03-09 10 views
1

私はASP.NET MVC Webアプリケーションでキャッシュを使用して、めったに更新されないリストデータを保存しようとしています。ASP.NETでキャッシュを使用する

HttpContext.Current.Cache.Insert("MyApp-Products", products, null, DateTime.Now.AddYears(99), Cache.NoSlidingExpiration); 

はその後、私のモデルでは、私はそれを取得:

public static List<string> GetProducts() 
{ 
    var cachedProducts = HttpContext.Current.Cache["MyApp-Products"]; 
    if (cachedProducts == null) 
    { 
     UpdateCache(); 
     cachedProducts = HttpContext.Current.Cache["MyApp-Products"]; 
    } 
    return ((List<string>)cachedProducts); 
} 

私は予想通りページ、UpdateCache()が呼び出された訪問は初めて私はこのようなUpdateCache()方法でキャッシュにこのデータを挿入します。リフレッシュすると、データはキャッシュから取得され、UpdateCache()に電話する必要はありません。しかし、15分後にアプリに戻り、キャッシュされた値はなくなりました。私の理解では、このキャッシュはセッション単位ではなくアプリケーション単位であったため、自分自身や他のユーザーのためにそこに存在することを期待していました。

キャッシュを保存する方法に問題がありますか?または、ASP.NETのCacheがどのようにWebアプリケーションで動作するのか分からないことがありますか?

+2

IISでアイドルタイムアウトとは何ですか?あなたのアプリケーションがシャットダウンしているだけですか?デフォルトは20分です。 –

+0

私はIISに慣れていません。 IISマネージャーでこの設定を見つけることはできますか? – Paul

+0

私はそれを見つけました。それが問題だと私は思う。ありがとう! – Paul

答えて

2

これは完全なIIS上にあり、15分ごとに発生します。アイドルタイムアウト値をチェックすることを忘れないでください。

言われているように、このリストが「決して」変化しないならば、代わりに静的な配列に格納してみてください。

+0

それはめったに変わらないが、決して変わらない。バックグラウンドで 'UpdateCache()'を定期的に呼び出す予定のタスクを定期的に実行する予定でした。 – Paul

+0

どこでIISのタイムアウト値を確認できますか? – Pankaj

+0

ApplicationPoolの[詳細プロパティ]にあります。 – Paul

5

私の理解では、このキャッシュは、アプリケーションごとに セッションではなかったということでしたので、私はそれはまだ自分自身や 他のユーザのためにそこにあることを期待しているでしょう。

キャッシュはアプリケーションごとにありますが、キャッシュに何かを保存しておけば、そこに戻ることが保証されません。たとえば、サーバーのメモリが不足しているなどのさまざまな状況下で、キャッシュが削除される可能性があります。イベントに登録して、アイテムがキャッシュから削除されたときに通知を受け取ることができます。また、アイテムをキャッシュするときに優先度を定義することもできます。優先度が高いほど、このアイテムが追い出される可能性は低くなります。

また、キャッシュはWebサーバーのメモリに保存されているため(デフォルトでは)、アプリケーションドメインがIISによっていつでもリサイクルできることを忘れないようにしてください。たとえば、ある量の非活動の後、またはメモリが不足し始めた場合、または特定のCPUしきい値の使用量に達した場合でも、キャッシュを含むメモリに格納されているすべてのものが無効になり、次の要求アプリケーションで新しいAppDomainが開始されます。

ただし、使用する前にアイテムがキャッシュに存在するかどうかを必ず確認してください。あなたが何かをそれに保管しておけば、それを見つけることができます。

このすべてのblablaはあなたのコードで非常に心配している本当に本質的なポイントに来る。 List<string>インスタンスをキャッシュに格納しているようです。しかし、キャッシュはアプリケーションごとであるため、List<string>のこの単一のインスタンスは、アプリケーションの複数のユーザー間で共有することができます。もちろん、これは同時に発生する可能性があります。あなたが知っている通り、List<T>はスレッドセーフな構造ではありません。したがってこのコードでは、せいぜい例外が発生し、最悪の場合は破損したデータが取得されます。したがって、あなたがキャッシングしているものと、スレッドセーフではないクラスをキャッシュしている場合は、構造体へのアクセスをどのように同期させているかを非常に注意してください。

+0

値を変更して問題にならないように思えるようには聞こえません。 IEnumerable を使用すると、これはより明確になります。 – Timbo

+0

読み取り専用のデータです。 IEnumerable を使用する方が良いでしょうか、それとも変更されていないかどうかは重要ですか? – Paul

+1

@Paul、それはあなたがデータでやっていることに依存します。例えば、索引を使用してリストの個々の要素にアクセスすることは、スレッドセーフです。これは実装の詳細です。一方、リストを列挙することはスレッドセーフではありません。したがって、このリストにforeachループを記述し、同じインスタンスでこのループを実行している2人の同時ユーザーがいる場合は、問題が発生する可能性があります。 –

0

一般的にデータベースにデータを格納する方が静的オブジェクトよりも優れていることがわかります。 の場合、データが変更された場合、アプリケーションよりもDBを更新する方が簡単です。

は、あなたのオブジェクトをキャッシュする際に明示的に絶対有効期限を設定してみてください:

HttpRuntime.Cache.Insert("MyApp-Products", cachedProducts, null, DateTime.Now.AddDays(20), TimeSpan.Zero); 

のhttpRuntimeは差が軽微であっても、パフォーマンス上の理由から、代わりにのHttpContextの使用されています。

関連する問題