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

Asp.Net何时删除过期的缓存项?,asp.net,caching,Asp.net,Caching,当您向System.Web.Caching.Cache添加一个具有绝对过期日期的项目时,如以下示例所示,Asp.Net的行为如何?它是否: 只需将项目标记为过期,然后在下次访问尝试时执行CacheItemRemovedCallback 从缓存中删除该项并立即执行CacheItemRemovedCallback HttpRuntime.Cache.Insert(key, new object(),

当您向
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似乎表明它立即发生。例如,“ASP.NET会在项目过期时自动从缓存中删除项目。”类似地,主题中的示例会说“如果调用
    GetReport
    [示例中的一个方法]之间的间隔超过15秒,ASP.NET会从缓存中删除报告。”

    尽管如此,这两项都不是明确的。他们没有说“立即执行回调”,我可以想象他们的作者可能认为上面的选项1算作“删除”一项。所以我做了一个快速而肮脏的测试,瞧,它似乎马上就要执行了——即使没有人访问我的站点,我也会定期收到60秒的回调

    然而,我的测试又快又脏,在对我的回答的评论中,有人建议Asp.Net实际上推迟回调的删除和执行,直到有人尝试再次访问缓存


    任何人都可以授权解决此问题,或者这只是一个实施细节吗?

    过期的项目不会立即从缓存中删除,它们只是标记为过期。除非缓存未命中,否则不会收到回调。我在ASP.NET 1.1中遇到了这个问题

    在某些情况下,过期的项目可能会被立即删除——比如内存不足,CPU占用率高——但你不能指望它

    我通常使用定时器定期重新加载缓存。

    万岁

    在以下任一情况下,过期的缓存项实际上会被删除(并调用回调):

    1) 有东西试图访问缓存项

    2)
    ExpiresBucket.FlusheExpiredItems
    方法运行并获取项。该方法是硬编码的,每20秒执行一次(StackOverflow问题的公认答案证实了我通过Reflector读取的代码)。但是,这需要额外的资格认证(请继续阅读)


    Asp.Net为服务器上的每个CPU维护一个缓存(我不确定这些CPU是代表逻辑还是物理CPU);其中每一个都维护一个
    CacheExpires
    实例,该实例有一个相应的
    计时器
    ,该计时器每二十秒调用一次它的
    FlusheExpiredItems
    方法

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

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

    所有这些都是连续发生的,因此有可能有什么东西会阻塞整个过程并导致延迟(并将缓存项的过期时间推回到指定的过期时间)

    但是,在这种时间分辨率下,最小过期间隔为20秒,进程中唯一可能阻塞较长时间的部分是执行
    CacheItemRemovedCallbacks
    。其中任何一个都可能阻塞给定的
    计时器
    FlusheExpiredItems
    线程indefinity。(虽然二十秒后,
    计时器
    将产生另一个
    FlusheExpiredItems
    线程。)


    总之,Asp.Net不能保证它将在指定的时间执行回调,但在某些情况下它会这样做。只要过期间隔超过20秒,并且只要缓存不必执行耗时的
    CacheItemRemovedCallbacks
    (全球范围-任何回调可能会干扰任何其他回调),它可以按计划执行过期回调。这对某些应用程序来说已经足够了,但对其他应用程序来说还不够。

    我认为这个问题没有权威的答案,因为正如Raymond Chen经常指出的那样,您将一个版本的软件行为解释为对所有未来版本都具有权威性s、 根据我的经验,这是一个坏主意,因为ASP.NET可能随时更改其行为并破坏您的应用程序。为什么不进行测试。在回调时,写入文件,查看创建日期及其与过期的关系。@dkackman-我不需要“现在和永远”回答,我愿意接受对.NET 2.0和3.5的权威性回答。对我来说,这似乎不仅仅是一个实现细节:我希望文档中会说,如果是这样的话,实际删除是不确定的。也许MS不同意。我只是想看看我是否只是忽略了文档中的某些内容ion。我喜欢你在文章中替代缓存过期的技术!但我仍然怀疑:我的测试站点已经运行了一整天,几乎没有其他任何东西在我的机器上运行,每分钟都尽职尽责地进行回调。为什么你说它们只被标记为过期?是因为你写的Steve Smith文章吗ink to?()他只说过期的缓存项不会被删除,而且……他说的是特定的缓存过期还是他使用的缓存过期,这一点还不清楚