代码之家  ›  专栏  ›  技术社区  ›  Yellowfog

任何ASP.NET数据缓存是否支持缓存项的后台填充?

  •  9
  • Yellowfog  · 技术社区  · 15 年前

    我们有一个数据驱动的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()的调用很昂贵,而且站点的使用也相当高。因此,每五分钟,当缓存下降时,站点就会变得非常“粘”起来,而许多请求都在等待新数据的检索。

    我们真正希望发生的是旧数据保持最新,而新数据定期在后台重新加载。(事实上,有人可能因此看到6分钟前的数据并不是一个大问题-数据不是 那个 时间敏感)。这是我可以自己写的东西,但是如果有其他缓存引擎(我知道像Velocity、Memcache这样的名称)支持这种情况,这将非常有用。或者我是否错过了标准ASP.NET数据缓存的一些明显技巧?

    3 回复  |  直到 15 年前
        1
  •  8
  •   Kelsey    15 年前

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

    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方法 缓存项的键和 您可能希望更新的原因 项目。这个的其余参数 方法是out参数。你提供 新缓存项和可选项 到期和相关性值 刷新缓存项时使用。

    如果 已显式删除缓存项 通过使用调用来移除()。

    如果希望缓存项 从缓存中删除,必须 在昂贵的对象中返回空值 参数。否则,您将返回 对新缓存数据的引用 使用昂贵的对象参数。 如果不指定过期时间或 依赖项值,该项将 仅当 需要内存。

    如果回调方法引发 异常,ASP.NET禁止 异常并移除缓存的 价值。

    我还没有测试过这个,所以你可能需要对它进行一些修改,但是它应该给你一个基本的想法,让你知道你想要完成什么。

        2
  •  0
  •   PhilPursglove    15 年前

    我可以看到 潜在的 此解决方案使用 AppFabric (以前称为“速度缓存”),因为它允许您 lock 缓存项,以便更新。当一个项目被锁定时,普通(非锁定)GET请求仍然正常工作,并返回缓存中该项目的当前副本。

    这样做也可以让你分开 GetDataFromSQL 方法到另一个进程,比如Windows服务,每五分钟运行一次,这将减轻您的“粘性”站点。


    或者…

    为什么不使用 SqlCacheDependency 当您将数据放入缓存中时,对象,以便只有当数据实际更改时才会刷新它。这样,您可以将数据缓存更长的时间,从而获得更好的性能,并且始终显示最新的数据。

    (顺便说一句,当你将对象放入缓存时,让你的意图更清晰的顶部提示-缓存有一个 NoSlidingExpiration (和) NoAbsoluteExpiration )常数可用,比您的时间跨度更可读。零)

        3
  •  0
  •   ZXX    15 年前

    首先,将实际需要的日期放在精益类(也称为POCO)中,而不是数据表中。

    第二,使用缓存和哈希-这样当您的时间依赖关系过期时,您可以生成一个异步委托来获取新数据,但旧数据在单独的哈希表中仍然是安全的(而不是字典-对于多个读卡器单编写器线程来说是不安全的)。

    根据数据类型和重组SQL的时间/预算,您可能只能获取更新窗口中最新写入时间较短的内容。您需要两步更新(必须将数据从保存的对象散列中复制到新对象中-散列中的内容对于任何用途都是严格只读的,否则地狱将被打破)。

    而sqlcacheDependency则因不可靠而臭名昭著,它会让系统陷入疯狂更新。

    推荐文章