我如何实现异步缓存?

6
我们正在使用以下模式来处理我们的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 用户)时,由于 CacheItemUpdateCallback 阻止其他线程执行,我们会看到 TTFB 急剧上升的情况,直到它从数据库中刷新缓存为止。
因此,我想到我们需要一个解决方案,即在缓存过期后,当第一个线程尝试访问它时,会触发异步线程来更新缓存,但仍允许所有其他执行线程从旧缓存中读取,直到它成功更新。
.NET 框架本身是否内置了能够处理我所要求的内容的任何组件或功能,或者我是否需要从头开始编写?请给出您的想法...
还有一点……
使用 HttpContext.Current.Cache 只是附带的,而不一定是必要的,因为我们可以使用单例模式上的私有成员来保存缓存数据。
请勿对缓存时间、SPROC 效率、我们为什么首先要进行缓存等事项发表评论,因为这与主题不相关。谢谢!
2个回答

0
经过数小时的调查,结果发现问题并不是我最初认为的CacheItemUpdateCallback阻塞了其他线程,事实上它异步地完成了我想要的操作,但是垃圾回收器停止一切来清理LOH。

请勿使用此模式来存储可能最终出现在 LOH 上的对象。 - James Law


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接