是否有任何asp.net数据缓存支持缓存条目的背景数量?

时间:2010-08-01 16:28:38

标签: asp.net caching

我们有一个数据驱动的ASP.NET网站,该网站使用标准模式进行数据缓存(从MSDN改编):

public DataTable GetData()
{
   string key = "DataTable";
   object item = Cache[key] as DataTable;
   if((item == null)
   {
      item = GetDataFromSQL();
      Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300), TimeSpan.Zero;
   }
   return (DataTable)item;
}

这样做的问题是对GetDataFromSQL()的调用很昂贵,并且该站点的使用相当高。因此,每隔五分钟,当缓存丢失时,网站变得非常“粘”,而很多请求都在等待检索新数据。

我们真正希望发生的是旧数据保持最新状态,而新数据会在后台定期重新加载。 (因此有人可能会看到六分钟的数据并不是一个大问题 - 数据 时间敏感)。这是我自己可以写的东西,但知道是否有任何替代缓存引擎(我知道像Velocity,memcache这样的名称)支持这种情况会很有用。或者我错过了标准ASP.NET数据缓存的一些明显技巧?

3 个答案:

答案 0 :(得分:8)

你应该能够使用CacheItemUpdateCallback委托,这是第6个参数,它是使用ASP.NET Cache的Insert的第4个重载:

Cache.Insert(key, value, dependancy, absoluteExpiration,
    slidingExpiration, onUpdateCallback);

以下内容应该有效:

Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300),
    Cache.NoSlidingExpiration, itemUpdateCallback);

private void itemUpdateCallback(string key, CacheItemUpdateReason reason,
    out object value, out CacheDependency dependency, out DateTime expiriation,
    out TimeSpan slidingExpiration)
{
    // do your SQL call here and store it in 'value'
    expiriation = DateTime.Now.AddSeconds(300);
    value = FunctionToGetYourData();
}

来自MSDN

  

当对象在缓存中到期时,   ASP.NET调用   CacheItemUpdateCallback方法用   缓存项的关键和   你可能想要更新的原因   项目。剩下的参数   方法是出参数。你供应   新的缓存项和可选项   到期和依赖值   刷新缓存项时使用。

     

如果是,则不会调用更新回调   缓存的项目被明确删除   通过调用Remove()。

     

如果您想要缓存的项目   你必须从缓存中删除   在expensiveObject中返回null   参数。否则,你返回一个   通过引用新的缓存数据   使用expensiveObject参数。   如果您没有指定过期或   依赖值,该项目将是   仅在缓存时从缓存中删除   记忆是必要的。

     

如果回调方法抛出一个   异常,ASP.NET抑制   异常并删除缓存   值。

我没有对此进行过测试,因此您可能需要稍微修补它,但它应该让您了解您想要完成的工作。

答案 1 :(得分:0)

我可以看到使用AppFabric(以前称为Velocity的缓存)有一个潜在的解决方案,因为它允许你lock一个缓存的项目,所以它可以更新。当项目被锁定时,普通(非锁定)Get请求仍然正常工作并返回缓存的项目的当前副本。

以这种方式执行此操作还可以将GetDataFromSQL方法分离到另一个进程,例如每五分钟运行一次的Windows服务,这样可以缓解您的“粘性”网站。


或者...

不是一次只缓存数据五分钟,为什么不在将数据放入缓存时使用SqlCacheDependency对象,这样只有在数据实际发生变化时才会刷新。这样,您可以将数据缓存更长时间,从而获得更好的性能,并且您将始终显示最新数据。

(顺便说一句,当您将对象放入缓存时,使您的意图更清晰的最佳提示 - 缓存有NoSlidingExpiration(和NoAbsoluteExpiration)常量,比Timespan更具可读性。零)

答案 2 :(得分:0)

首先,将实际需要的日期放在精益课程(也称为POCO)中,而不是那个DataTable猪。

其次,使用缓存和哈希 - 这样当你的时间依赖关系到期时,你可以产生一个异步委托来获取新数据,但你的旧数据在单独的哈希表中仍然是安全的(不是字典 - 它对于多读者来说不安全单一作家线程)。

根据数据类型和重构SQL端的时间/预算,您可能只能获取比更新窗口更年轻的LastWrite。你将需要两步更新(必须将哈希保存的对象中的dats复制到新对象中 - 哈希中的东西严格地只读用于任何用途或者地狱会破坏)。

哦,SqlCacheDependency因为不可靠而臭名昭着,可能会让您的系统陷入疯狂的更新。