【发布时间】:2011-12-04 01:53:35
【问题描述】:
我们使用以下模式为我们的 asp.net 应用程序处理通用对象的缓存。
private object SystemConfigurationCacheLock = new object();
public SystemConfiguration SystemConfiguration
{
get
{
if (HttpContext.Current.Cache["SystemConfiguration"] == null)
lock (SystemConfigurationCacheLock)
{
if (HttpContext.Current.Cache["SystemConfiguration"] == null)
HttpContext.Current.Cache.Insert("SystemConfiguration", GetSystemConfiguration(), null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration, new CacheItemUpdateCallback(SystemConfigurationCacheItemUpdateCallback));
}
return HttpContext.Current.Cache["SystemConfiguration"] as SystemConfiguration;
}
}
private void SystemConfigurationCacheItemUpdateCallback(string key, CacheItemUpdateReason reason, out object expensiveObject, out CacheDependency dependency, out DateTime absoluteExpiration, out TimeSpan slidingExpiration)
{
dependency = null;
absoluteExpiration = DateTime.Now.AddMinutes(1);
slidingExpiration = Cache.NoSlidingExpiration;
expensiveObject = GetSystemConfiguration();
}
private SystemConfiguration GetSystemConfiguration()
{
//Load system configuration
}
问题在于,在负载下(约 100,000 个用户)我们会看到 TTFB 中的巨大跳跃,因为 CacheItemUpdateCallback 会阻止所有其他线程执行,直到它完成从数据库中刷新缓存。
所以我认为我们需要的解决方案是,当缓存过期后的第一个线程尝试访问它时,会触发一个异步线程来更新缓存,但仍然允许所有其他执行线程从旧缓存中读取直到它成功更新。
.NET 框架中是否有任何东西可以本地处理我的要求,或者我必须从头开始编写它?请您的想法...
有几件事...
HttpContext.Current.Cache 的使用是偶然的,不一定是必要的,因为我们在单例中使用私有成员来保存缓存数据没有问题。
请不要评论缓存时间、SPROC 效率、为什么我们首先要缓存等,因为这无关紧要。谢谢!
【问题讨论】: