ASP.net 缓存绝对过期不起作用

Posted

技术标签:

【中文标题】ASP.net 缓存绝对过期不起作用【英文标题】:ASP.net Cache Absolute Expiration not working 【发布时间】:2011-08-19 14:58:28 【问题描述】:

我在 HttpContext.Cache 中存储一个整数值,其绝对过期时间为 5 分钟后。但是,在等待 6 分钟(或更长时间)后,整数值仍在缓存中(即,即使绝对过期已经过去,它也不会被删除)。这是我正在使用的代码:

public void UpdateCountFor(string remoteIp)

    // only returns true the first time its run
    // after that the value is still in the Cache
    // even after the absolute expiration has passed
    // so after that this keeps returning false
    if (HttpContext.Current.Cache[remoteIp] == null)
    
        // nothing for this ip in the cache so add the ip as a key with a value of 1
        var expireDate = DateTime.Now.AddMinutes(5);
        // I also tried:
        // var expireDate = DateTime.UtcNow.AddMinutes(5); 
        // and that did not work either.
        HttpContext.Current.Cache.Insert(remoteIp, 1, null, expireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    
    else
    
        // increment the existing value
        HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;
    

我第一次运行 UpdateCountFor("127.0.0.1") 时,它将 1 插入到缓存中,键为“127.0.0.1”,并且从现在开始的绝对到期时间为 5 分钟,正如预期的那样。然后每次后续运行都会增加缓存中的值。但是,在等待 10 分钟后,它会继续增加 Cache 中的值。该值永不过期,也永远不会从缓存中删除。这是为什么呢?

据我了解,绝对过期时间意味着该项目大约会在那个时候被删除。难道我做错了什么?我是不是误会了什么?

我预计该值会在 5 分钟后从缓存中删除,但它会一直保留在那里,直到我重建项目。

这一切都在我本地机器上的 .NET 4.0 上运行。

【问题讨论】:

你的 web.config 中有什么奇怪的缓存配置设置吗? 不,我有默认的 web.config 【参考方案1】:

原来这一行:

HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;

删除之前的值并重新插入没有绝对或滑动到期时间的值。为了解决这个问题,我必须创建一个辅助类并像这样使用它:

public class IncrementingCacheCounter

    public int Count;
    public DateTime ExpireDate;


public void UpdateCountFor(string remoteIp)

    IncrementingCacheCounter counter = null;
    if (HttpContext.Current.Cache[remoteIp] == null)
    
        var expireDate = DateTime.Now.AddMinutes(5);
        counter = new IncrementingCacheCounter  Count = 1, ExpireDate = expireDate ;
    
    else
    
        counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
        counter.Count++;
    
    HttpContext.Current.Cache.Insert(remoteIp, counter, null, counter.ExpireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);

这将解决这个问题,让计数器在绝对时间正确过期,同时仍对其进行更新。

【讨论】:

这是API太有用的情况。而不是强迫你使用你看到的索引器的存储机制会导致奇怪 我同意。我最终只是使用ilspy 浏览了源代码以找出所有这些。【参考方案2】:

尝试使用 DateTime.UtcNow 而不是 datetime.Now 来计算您的超时时间。您可能会遇到以下问题:

absoluteExpiration 类型: System.DateTime 插入的对象过期并被删除 从缓存中。 为了避免可能 本地时间问题,例如更改 从标准时间到夏令时 时间,使用 UtcNow 而不是 Now 这个参数值。如果你正在使用 绝对到期 滑动过期参数必须是 NoSlidingExpiration。

【讨论】:

将其更改为使用 DateTime.UtcNow.AddMinutes(5);没用:( 无赖我认为你的代码是正确的。在我看来是对的。它什么时候从缓存中删除? .您可以向 cache.insert 添加回调以了解它何时被删除。也许这会给你一些关于触发它的线索。 就是这样,它根本不会从缓存中删除。这就是我遇到的问题。我预计它会在 5 分钟后被删除,但它会一直保留在那里,直到我重建项目。 TimeSpan.FromMinutes(number_of_minutes)【参考方案3】:

有一个比 smoak 发布的更简单的答案。使用该示例作为起点,下面的更新代码可以工作并且不需要重新插入。之所以可行,是因为类是引用类型。因此,当您更新类实例中的计数器时,它不会导致缓存触发更新。

public class IncrementingCacheCounter

    public int Count;


public void UpdateCountFor(string remoteIp)

    IncrementingCacheCounter counter = null;
    if (HttpContext.Current.Cache[remoteIp] == null)
    
        counter = new IncrementingCacheCounter  Count = 1;
        HttpContext.Current.Cache.Insert(remoteIp, counter, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    
    else
    
        counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
        counter.Count++;
    

【讨论】:

以上是关于ASP.net 缓存绝对过期不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net 缓存在 IIS 上不起作用。 IIS上有没有设置

自定义授权过滤器在 ASP.NET Core 3 中不起作用

QueryStringParameters 在 ASP.Net objectDataSource 上不起作用

下拉列表在 asp.net 的移动视图中不起作用

ASP.NET - 模拟不起作用

ASP.NET Identity 2.0 注销不起作用