为ASP.NET中的第一个访问者设置Cache对象

时间:2014-02-02 19:41:56

标签: asp.net multithreading caching locking

我有一个网站,它将从数据库中检索一些繁重的数据并将其存储到缓存对象中。但是,在高峰时段,如果缓存对象已过期且所有用户同时检索数据,则我的网站变得非常慢(CPU 100%),并且网站与数据库之间的连接将超时。结果,缓存对象将变空。

每次缓存对象过期时,对我来说都是临时解决方案。我必须通过将所有用户重定向到静态页面来停止所有用户。然后清除缓存对象并以管理员身份访问页面(目前只允许管理员访问)以生成缓存对象。之后,我将再次启用该页面,用户可以照常访问该页面。

我在想,是否有可能使其每当高速缓存对象过期,当页面第一访问者只能访问(在高峰时段,这可能是最多50个用户访问该页面缓存对象将被创建在同一时间),访问该页面的其余用户必须等到创建缓存对象(停止它们以调用创建缓存对象模块)。

当前它的工作原理是每次用户访问此页面时,都会检查缓存对象。如果为null,则它将从数据库中检索HeavyData

if (Cache[ID] == null)
    {
        HeavyData = RetrieveHeavyDataFromDatabase(); // retrieve data from db 
        Cache.Insert(ID, HeavyData, null, DateTime.Now.AddMinutes(720)), System.Web.Caching.Cache.NoSlidingExpiration);
    }

2 个答案:

答案 0 :(得分:2)

问题可能是多个请求正在尝试重新创建缓存。

只需在你的单身人士周围添加一个锁定对象和一个if-lock-if包装器。在填充缓存之前,这仍将保留每个请求,但将确保只有1个请求将进入繁重的进程。

http://en.wikipedia.org/wiki/Double-checked_locking

private static object lockObject = new object();

if (Cache[ID] == null)
{
    lock(lockObject)
    {
        if (Cache[ID] == null)
        {
             HeavyData = RetrieveHeavyDataFromDatabase(); // retrieve data from db 
             Cache.Insert(ID, HeavyData, null, DateTime.Now.AddMinutes(720)), System.Web.Caching.Cache.NoSlidingExpiration);
        }
    }
}

答案 1 :(得分:1)

你应该在它周围包装一个锁定语句。它将确保只有一个线程可以进行重度检索。

static Object lockObject = new Object();
lock(lockObject)
{
    if (Cache[ID] == null)
    {
        HeavyData = RetrieveHeavyDataFromDatabase(); // retrieve data from db 
        Cache.Insert(ID, HeavyData, null, DateTime.Now.AddMinutes(720)), System.Web.Caching.Cache.NoSlidingExpiration);
    }
}