我有一个网站,它将从数据库中检索一些繁重的数据并将其存储到缓存对象中。但是,在高峰时段,如果缓存对象已过期且所有用户同时检索数据,则我的网站变得非常慢(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);
}
答案 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);
}
}