我正在尝试使用ASP.NET MVC Web应用程序中的缓存来存储一些很少更新的列表数据。我使用UpdateCache()
方法将此数据插入缓存中,如下所示:
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()
。然而,在大约15分钟之后,我回到应用程序并且缓存的值已经消失。我的理解是这个缓存是每个应用程序,而不是会话,所以我希望它仍然存在于我自己或其他用户。
我存储缓存的方式有问题吗?或者是否有一些我不了解ASP.NET中的Cache
如何在Web应用程序中运行?
答案 0 :(得分:5)
我的理解是这个缓存是针对每个应用程序而不是 会话,所以我原本以为它仍然会在那里为我自己或 另一个用户。
虽然缓存是针对每个应用程序的,但是ASP.NET并没有为您提供任何保证,如果您将某些内容存储到缓存中,您将在那里找到它。缓存可能在不同情况下被逐出,例如您的服务器开始内存不足等等。您可以订阅事件,并在项目从缓存中逐出时收到通知。您还可以在缓存项目时定义优先级。优先级越高,此项目被驱逐的可能性越低。
此外,由于缓存存储在Web服务器的内存中(默认情况下),因此您不应忘记IIS可以在任何时候回收您的应用程序域。例如,在一定量的不活动之后或者它开始在内存上运行不足或者即使达到某个CPU阈值使用时,......并且存储在包括缓存的存储器中的所有内容将简单地消失在空白和下一个请求中在您的应用程序中将启动一个新的AppDomain。
但在任何情况下都要确保在使用之前检查项目是否存在于缓存中。永远不要依赖这样一个事实:如果你把东西存入其中,你会发现它。
所有这些blabla来到真正重要的一点,这是你的代码非常令人担忧。看起来您正在将List<string>
实例存储到缓存中。但由于缓存是针对每个应用程序的,因此List<string>
的这个单个实例可以在应用程序的多个用户之间共享,当然这可能同时发生。如您所知List<T>
不是线程安全的结构。因此,使用此代码,您最多会获得异常,最坏的情况是您将获得损坏的数据。因此,要非常小心缓存以及如何同步对结构的访问,尤其是在缓存非线程安全的类时。
答案 1 :(得分:2)
如果这是一个完整的IIS,并且每15分钟左右发生一次。请记住检查空闲超时值。
话虽如此,如果这个列表“永远不会”改变,为什么不将它存储在静态数组中呢。
答案 2 :(得分:0)
我可以看到如何在数据库中存储数据比在静态对象中更好。 例如,如果数据发生变化,则更新DB比应用程序更容易。
在缓存对象时尝试显式设置绝对过期:
HttpRuntime.Cache.Insert("MyApp-Products", cachedProducts, null, DateTime.Now.AddDays(20), TimeSpan.Zero );
注意 HttpRuntime 代替 HttpContext 出于性能原因,即使差异很小。