我们有一个数据驱动的ASP.NET网站,该网站使用标准模式进行数据缓存(从MSDN改编):
public DataTable GetData()
{
string key = "DataTable";
object item = Cache[key] as DataTable;
if((item == null)
{
item = GetDataFromSQL();
Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300), TimeSpan.Zero;
}
return (DataTable)item;
}
这样做的问题是对GetDataFromSQL()的调用很昂贵,并且该站点的使用相当高。因此,每隔五分钟,当缓存丢失时,网站变得非常“粘”,而很多请求都在等待检索新数据。
我们真正希望发生的是旧数据保持最新状态,而新数据会在后台定期重新加载。 (因此有人可能会看到六分钟的数据并不是一个大问题 - 数据 时间敏感)。这是我自己可以写的东西,但知道是否有任何替代缓存引擎(我知道像Velocity,memcache这样的名称)支持这种情况会很有用。或者我错过了标准ASP.NET数据缓存的一些明显技巧?
答案 0 :(得分:8)
你应该能够使用CacheItemUpdateCallback
委托,这是第6个参数,它是使用ASP.NET Cache的Insert
的第4个重载:
Cache.Insert(key, value, dependancy, absoluteExpiration,
slidingExpiration, onUpdateCallback);
以下内容应该有效:
Cache.Insert(key, item, null, DateTime.Now.AddSeconds(300),
Cache.NoSlidingExpiration, itemUpdateCallback);
private void itemUpdateCallback(string key, CacheItemUpdateReason reason,
out object value, out CacheDependency dependency, out DateTime expiriation,
out TimeSpan slidingExpiration)
{
// do your SQL call here and store it in 'value'
expiriation = DateTime.Now.AddSeconds(300);
value = FunctionToGetYourData();
}
来自MSDN:
当对象在缓存中到期时, ASP.NET调用 CacheItemUpdateCallback方法用 缓存项的关键和 你可能想要更新的原因 项目。剩下的参数 方法是出参数。你供应 新的缓存项和可选项 到期和依赖值 刷新缓存项时使用。
如果是,则不会调用更新回调 缓存的项目被明确删除 通过调用Remove()。
如果您想要缓存的项目 你必须从缓存中删除 在expensiveObject中返回null 参数。否则,你返回一个 通过引用新的缓存数据 使用expensiveObject参数。 如果您没有指定过期或 依赖值,该项目将是 仅在缓存时从缓存中删除 记忆是必要的。
如果回调方法抛出一个 异常,ASP.NET抑制 异常并删除缓存 值。
我没有对此进行过测试,因此您可能需要稍微修补它,但它应该让您了解您想要完成的工作。
答案 1 :(得分:0)
我可以看到使用AppFabric(以前称为Velocity的缓存)有一个潜在的解决方案,因为它允许你lock一个缓存的项目,所以它可以更新。当项目被锁定时,普通(非锁定)Get请求仍然正常工作并返回缓存的项目的当前副本。
以这种方式执行此操作还可以将GetDataFromSQL
方法分离到另一个进程,例如每五分钟运行一次的Windows服务,这样可以缓解您的“粘性”网站。
或者...
不是一次只缓存数据五分钟,为什么不在将数据放入缓存时使用SqlCacheDependency对象,这样只有在数据实际发生变化时才会刷新。这样,您可以将数据缓存更长时间,从而获得更好的性能,并且您将始终显示最新数据。
(顺便说一句,当您将对象放入缓存时,使您的意图更清晰的最佳提示 - 缓存有NoSlidingExpiration
(和NoAbsoluteExpiration
)常量,比Timespan更具可读性。零)
答案 2 :(得分:0)
首先,将实际需要的日期放在精益课程(也称为POCO)中,而不是那个DataTable猪。
其次,使用缓存和哈希 - 这样当你的时间依赖关系到期时,你可以产生一个异步委托来获取新数据,但你的旧数据在单独的哈希表中仍然是安全的(不是字典 - 它对于多读者来说不安全单一作家线程)。
根据数据类型和重构SQL端的时间/预算,您可能只能获取比更新窗口更年轻的LastWrite。你将需要两步更新(必须将哈希保存的对象中的dats复制到新对象中 - 哈希中的东西严格地只读用于任何用途或者地狱会破坏)。
哦,SqlCacheDependency因为不可靠而臭名昭着,可能会让您的系统陷入疯狂的更新。