更改 ASP.NET 缓存项过期的频率?

Posted

技术标签:

【中文标题】更改 ASP.NET 缓存项过期的频率?【英文标题】:Changing frequency of ASP.NET cache item expiration? 【发布时间】:2010-09-21 01:46:35 【问题描述】:

我注意到 ASP.NET 缓存项每 20 秒检查一次(并且可能会被删除)(奇怪的是每次都在 HH:MM:00、HH:MM:20 和 HH:MM:40)。我花了大约 15 分钟寻找如何更改此参数,但没有成功。我还尝试在 web.config 中设置以下内容,但没有帮助:

<cache privateBytesPollTime="00:00:05" />

我并不想做任何疯狂的事情,但是如果它是 5 秒而不是 20 秒,或者对于我的应用程序来说至少是 10 秒,那就太好了。

【问题讨论】:

【参考方案1】:

使用 Reflector 进行探索发现间隔是硬编码的。过期由内部CacheExpires 类处理,其静态构造函数包含

_tsPerBucket = new TimeSpan(0, 0, 20);

_tsPerBucketreadonly,所以以后不能有任何配置设置修改它。

然后在CacheExpires.EnableExpirationTimer()...中设置将触发检查过期项目的计时器...

DateTime utcNow = DateTime.UtcNow;
TimeSpan span = _tsPerBucket - new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks);
this._timer = new Timer(new TimerCallback(this.TimerCallback), null,
    span.Ticks / 0x2710L, _tsPerBucket.Ticks / 0x2710L);

span 的计算确保计时器准确地在 :00、:20、:40 秒触发,但我看不出有任何打扰的理由。定时器调用的方法是internal,所以我认为没有办法设置自己的定时器来更频繁地调用它(忽略反射)。

不过,好消息是您不应该真的有任何理由关心间隔。 Cache.Get() 检查项目是否过期,如果过期则立即从缓存中删除项目并返回 null。因此,您永远不会从缓存中获取过期项目,即使过期项目可能会在缓存中停留长达 20 秒。

【讨论】:

【参考方案2】:

根据documentation,privateBytesPollTime 用于“工作进程内存使用”,默认为 1 秒。我认为这与缓存项删除无关。

我确实使用项目删除回调确认了您的结果 - 看起来项目在分钟的底部、:20 和 :40 秒被删除。这表明项目可能会在缓存中保留长达 20 秒,超过对它们设置的 AbsoluteExpiration。我找不到任何说明是否可以更改 20 秒轮询间隔的文档。

【讨论】:

【参考方案3】:

疯狂但有效的解决方案(需要所有步骤):

// New value for cache expiration cycle
// System.Web.Caching.CacheExpires._tsPerBucket;
// Set 1 seconds instead of 20sec
const string assembly = "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Web.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));

// Recreate cache
// HttpRuntime._theRuntime._cacheInternal = null;
// HttpRuntime._theRuntime._cachePublic = null;
type = typeof (HttpRuntime);
field = type.GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
var runtime = field.GetValue(null);
field = type.GetField("_cachePublic", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
field = type.GetField("_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);

【讨论】:

以上是关于更改 ASP.NET 缓存项过期的频率?的主要内容,如果未能解决你的问题,请参考以下文章

缓存失效

实现自定义 CacheDependency 以使 ASP.Net 缓存项无效

.Net Core MemoryCache PostEvictionCallback 无法正常工作

如何在 asp.net core 中遍历 MemoryCache?

Redis:基于依赖项的缓存项失效?

如何清除Oracle中的所有缓存项