2012-03-09 62 views
1

我想在ASP.NET MVC Web应用程序中使用缓存来存储一些很少更新的列表数据。我插入这个数据到高速缓存中的UpdateCache()方法是这样的:在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()。然而,在大概15分钟后,我回到了应用程序,缓存的值也消失了。我的理解是,这是缓存每个应用程序,而不是会话,所以我本来期望它仍然在那里为自己或其他用户。

我存储缓存的方式有什么问题吗?或者是有什么我不理解关于ASP.NET中的Cache如何在一个web应用程序?

+2

什么是您在IIS中的空闲超时?仅仅是你的应用程序正在关闭?默认是20分钟。 – 2012-03-09 22:42:47

+0

我对IIS不太熟悉。我可以在IIS管理器中找到这个设置吗? – Paul 2012-03-09 23:26:26

+0

我找到了。我认为这是问题。谢谢! – Paul 2012-03-09 23:44:29

回答

2

如果这是在完整的IIS上,并且每隔15分钟左右发生一次。请记住检查空闲超时值。

话虽这么说,如果此列表“从不”的变化,为什么不将其存储在一个静态数组来代替。

+0

它很少变化,但不是永远不变。我打算运行一个计划任务,在后台定期调用'UpdateCache()'。 – Paul 2012-03-09 23:30:56

+0

我在哪里可以检查IIS中的超时值? – Pankaj 2012-03-10 01:07:57

+0

它位于ApplicationPool的高级属性下。 – Paul 2012-03-10 20:06:20

5

我的理解是,这是缓存每个应用程序,而不是 会议,所以我本来期望它仍然在那里为自己或 其他用户。

虽然缓存为每个应用程序,ASP.NET不会向您提供任何保证,如果你的东西存储到缓存中,你会发现它回到那里。缓存可能会在不同情况下被逐出,例如您的服务器开始在内存中运行不足等等。您可以订阅一个事件,并在物品从缓存中被驱逐时收到通知。您还可以在缓存项目时定义优先级。优先级越高,这个项目被驱逐的机会就越小。

此外,由于缓存存储在Web服务器的内存中(默认情况下),您不应该忘记您的应用程序域可以在任何时候由IIS回收。例如一定量的闲置后,或者如果它开始运行内存不足或者即使某一个CPU阈值usageis达到...并存储在该存储器包括高速缓存将简单地消失在虚空下一请求一切在你的应用程序中将启动一个新的AppDomain。

但在任何情况下,请确保在使用它之前检查项目是否存在于缓存中。永远不要依赖这样一个事实,即如果你存储了一些东西,你会发现它。

所有这些blabla来到真正的基本点,这是非常令人担忧的代码。它看起来像是将一个List<string>实例存储到缓存中。但由于缓存每个应用程序中,这List<string>单个实例可以被应用,当然这可能同时发生的多个用户之间共享。正如你所知,List<T>不是线程安全结构。因此,使用此代码,您最多只会得到一个异常,最糟糕的情况是您会收到损坏的数据。所以要非常小心你的缓存和你如何同步,特别是如果你正在缓存非线程安全类的访问结构。

+0

这听起来不像他想改变的价值,所以它可能不是一个问题。使用IEnumerable 会使这个更清晰。 – Timbo 2012-03-09 22:57:24

+0

它是只读数据。使用IEnumerable 还是更好一些,或者它没有被修改是否重要? – Paul 2012-03-09 23:29:18

+1

@Paul,这取决于你对数据做了什么。例如,使用读取索引访问列表的各个元素是线程安全的。尽管这是一个实现细节。另一方面枚举列表不是线程安全的。所以如果你在这个列表上编写一个foreach循环,并且你有两个并发用户在同一个实例上运行这个循环,你可能会遇到麻烦。 – 2012-03-09 23:34:47

0

我可以看到如何在数据库中存储一般的数据比静态对象更好。 首先,如果数据确实发生变化,则更新数据库比应用程序更容易。

尝试缓存的对象时明确设置绝对过期:

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

的httpRuntime是用来代替的HttpContext性能方面的原因,即使差异是次要的。