asp.net - Asp.Net何时删除过期的缓存项?

标签 asp.net caching

当您将一个具有绝对到期日期的项目添加到System.Web.Caching.Cache中时,如以下示例所示,Asp.Net的行为如何?可以:

  • 只需将项目标记为过期,然后在下次访问尝试时执行CacheItemRemovedCallback
  • 从缓存中删除项目并立即执行CacheItemRemovedCallback吗?
    HttpRuntime.Cache.Insert(key,
                             new object(),
                             null, 
                             DateTime.Now.AddSeconds(seconds), 
                             Cache.NoSlidingExpiration,
                             CacheItemPriority.NotRemovable, 
                             OnCacheRemove);
    

  • MSDN似乎表明它立即发生。例如,the "Expiration" section of the "ASP.NET Caching Overview"说“ASP.NET在过期时会自动从缓存中删除它们”。同样,主题"How to: Notify an Application When an Item Is Removed from the Cache"中的示例说:“如果两次调用GetReport(示例中的方法)之间的时间间隔超过15秒,则ASP.NET将从缓存中删除报告。”

    尽管如此,这些都不是明确的。他们不会说“回调会立即执行”,我可以想象他们的作者可能如何认为上述选项1被视为“删除”了一项。因此,我进行了一次快速而肮脏的测试,瞧,它似乎立即开始执行-即使没有人访问我的网站,我也会得到定期的60秒回调。

    但是,我的测试又快又脏,在有人回答Is there a way to run a process every day in a .Net web application without writing a windows service or SQL server jobs的评论中,有人建议Asp.Net实际上推迟了回调的删除和执行,直到某些东西试图再次访问缓存为止。

    任何人都可以权威地解决这个问题,或者这仅仅是实现细节?

    最佳答案

    Reflector欢呼!

    发生以下情况时,实际上将删除过期的缓存项(并调用回调):

    1)某些东西试图访问缓存项。

    2)ExpiresBucket.FlushExpiredItems方法运行并转到项目。此方法被硬编码为每20秒执行一次(已接受的StackOverflow问题Changing frequency of ASP.NET cache item expiration答案证实了我通过Reflector对该代码的读取)。但是,这需要附加的限定条件(请继续阅读)。

    Asp.Net为服务器上的每个CPU维护一个缓存(我不确定它们是否代表逻辑或物理CPU)。每个实例都维护一个CacheExpires实例,该实例具有一个对应的Timer,每20秒调用一次FlushExpiredItems方法。

    此方法依次迭代缓存过期数据的另一个“桶”集合(一个ExpiresBucket实例数组),依次调用每个桶的FlushExpiredItems方法。

    此方法(ExpiresBucket.FlushExpiredItems)首先迭代存储桶中的所有缓存项目,如果某个项目已过期,则将其标记为已过期。然后(在这里我要简化),迭代它标记为已过期的项目并删除它们,执行CacheItemRemovedCallback(实际上,它调用CacheSingle.Remove,后者先调用CacheInternal.DoRemove,然后再调用CacheSingle.UpdateCache,然后再调用CacheEntry.Close,而后者实际上会调用回调)。

    所有这些都是串行发生的,因此有可能会阻塞整个过程并阻止事情(并从指定的过期时间推迟缓存项的过期)。

    但是,在此时间分辨率下,以20秒的最小到期时间间隔,可能会阻塞相当长的时间长度的过程的唯一部分是CacheItemRemovedCallbacks的执行。这些中的任何一个都可以无限期地阻塞给定的TimerFlushExpiredItems线程。 (尽管二十秒后,Timer会生成另一个FlushExpiredItems线程。)

    总而言之,Asp.Net不保证它将在指定的时间执行回调,但是在某些情况下会这样做。只要到期间隔相隔二十秒以上,并且只要高速缓存不必执行耗时的CacheItemRemovedCallbacks(全局-任何回调都可能会干扰其他任何回调),它就可以按计划执行到期回调。对于某些应用程序来说这已经足够了,但对于其他应用程序却不够。

    关于asp.net - Asp.Net何时删除过期的缓存项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1434284/

    相关文章:

    c# - 动态更改母版页

    asp.net - 在哪里可以获得用于 SQL Server 的简单时区表?

    php - Redis读写基本概念

    caching - NGINX try_files 具有多个命名位置

    javascript - 如何强制重新加载缓存的 HTML 文件

    用于下载文件而无需另存为的 Java Applet

    jQuery:如何从文件上传控件获取文件名?

    asp.net - IIS7环境下Application_Start异常处理

    swift - 防止 NSURLSession 缓存响应

    AJAX post 请求对不同的请求返回相同的响应