如何实现异步缓存?

Jam*_*Law 6 c# asp.net

我们使用以下模式来处理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
} 
Run Code Online (Sandbox Code Playgroud)

问题是当负载不足(~100,000个用户)时,我们看到TTFB出现大幅跳跃,因为CacheItemUpdateCallback阻止所有其他线程执行,直到它完成从数据库刷新缓存.

所以我认为我们需要的是解决方案,当缓存到期后的第一个线程试图访问它时,会触发异步线程来更新缓存,但仍允许所有其他执行线程从旧缓存中读取,直到它具有成功更新.

.NET框架中是否有内置可以处理我所要求的内容,或者我是否必须从头开始编写它?请你的想法......

有几件事......

HttpContext.Current.Cache的使用是偶然的,并不一定是必要的,因为我们在单例上使用私有成员来保存缓存数据没有问题.

请不要评论缓存时间,SPROC效率,为什么我们首先缓存等等,因为它不相关.谢谢!

Jam*_*Law 0

经过几个小时的调查,结果发现问题并不像我最初想象的那样 CacheItemUpdateCallback 阻塞其他线程,事实上它完全按照我想要的方式异步执行,而是垃圾收集器停止了所有操作以清理 LOH。