【问题标题】:How do I implement asynchrounous caching?如何实现异步缓存?
【发布时间】: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 效率、为什么我们首先要缓存等,因为这无关紧要。谢谢!

【问题讨论】:

    标签: c# asp.net


    【解决方案1】:
    【解决方案2】:

    所以经过几个小时的调查后发现,问题不是我最初认为的 CacheItemUpdateCallback 阻塞了其他线程,实际上它完全按照我的意愿异步执行,而是垃圾收集器停止了一切以清理哈哈。

    【讨论】:

    • 不使用此模式来存储可能随后会出现在 LOH 上的对象。
    猜你喜欢
    • 1970-01-01
    • 2016-03-11
    • 2016-05-16
    • 1970-01-01
    • 2011-10-05
    • 2012-07-08
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多