绝对到期此示例将对受时间影响的数据缓存一分钟一分钟过后缓存将到期注意绝对到期和滑动到期(见下文)不能一起使用
CacheInsert(key myFrequentlyAccessedData null
SystemWebCachingCacheNoAbsoluteExpiration
TimeSpanFromMinutes());
滑动到期此示例将缓存一些频繁使用的数据数据将在缓存中一直保留下去除非数据未被引用的时间达到了一分钟注意滑动到期和绝对到期不能一起使用
更多选项
除了上面提到的依赖项我们还可以指定项的优先级(依次为 lowhighNotRemovable它们是在 SystemWebCachingCacheItemPriority 枚举中定义的)以及当缓存中的项到期时调用的
CacheItemRemovedCallback 函数大多数时候默认的优先级已经足够了 — 缓存引擎可以正常完成任务并处理缓存的内存管理CacheItemRemovedCallback 选项考虑到一些很有趣的可能性但实际上它很少使用不过为了说明该方法我将提供它的一个使用示例
CacheItemRemovedCallback 示例
SystemWebCachingCacheItemRemovedCallback callback = new SystemWebCachingCacheItemRemovedCallback (OnRemove);
CacheInsert(keymyFilenull
SystemWebCachingCacheNoAbsoluteExpiration
TimeSpanZero
SystemWebCachingCacheItemPriorityDefault callback);
public static void OnRemove(string key
object cacheItem
SystemWebCachingCacheItemRemovedReason reason)
{
AppendLog(The cached value with key + key +
was removed from the cache Reason: +
reasonToString());
}
该示例将使用 AppendLog() 方法(这里不讨论该方法请参阅 Writing Entries to Event Logs)中定义的任何逻辑来记录缓存中的数据到期的原因通过在从缓存中删除项时记录这些项并记录删除的原因您可以确定是否在有效地使用缓存或者您是否可能需要增加服务器上的内存注意callback 是一个静态(在 VB 中为 Shared)方法建议使用该方法的原因是如果不使用它保存回调函数的类的实
例将保留在内存中以支持回调(对 static/Shared 方法则没有必要)
该特性有一个潜在的用处 — 在后台刷新缓存的数据这样用户永远都不必等待数据被填充但数据始终保持相对较新的状态但实际上此特性并不适用于当前版本的缓存 API因为在从缓存中删除缓存的项之前不触发或不完成回调因此用户将频繁地发出尝试访问缓存值的请求然后发现缓存值为空不得不等待缓存值的重新填充我希望在未来的 ASPNET 版本中看到一个附加的回调可以称为 CachedItemExpiredButNotRemovedCallback如果定义了该回调则必须在删除缓存项之前完成执行
缓存数据引用模式
每当我们尝试访问缓存中的数据时都应该考虑到一种情况那就是数据可能已经不在缓存中了因此下面的模式应该普遍适用于您对缓存的数据的访问在这种情况下我们假定已缓存的数据是一个数据表
public DataTable GetCustomers(bool BypassCache)
{
string cacheKey = CustomersDataTable;
object cacheItem = Cache[cacheKey] as DataTable;
if((BypassCache) (cacheItem == null))
{
cacheItem = GetCustomersFromDataSource();
CacheInsert(cacheKey cacheItem null
DateTimeNowAddSeconds(GetCacheSecondsFromConfig(cacheKey)
TimeSpanZero);
}
return (DataTable)cacheItem;
}
关于此模式有以下几点需要注意
? 某些值(例如cacheKeycacheItem 和缓存持续时间)是一次定义的并且只定义一次
? 可以根据需要跳过缓存 — 例如当注册一个新客户并重定向到客户列表后最好的做法可能就是跳过缓存用最新数据重新填充缓存该数据包括新插入的客户
? 缓存只能访问一次这种做法可以提高性能并确保不会发生 NullReferenceExceptions因为该项在第一次被检查时是存在的但第二次检查之前就已经到期了
? 该模式使用强类型检查C# 中的 as 运算符尝试将对象转换为类型如果失败或该对象为空则只返回 null(空)
? 持续时间存储在配置文件中在理想的情况下所有的缓存依赖项(无论是基于文件的或是基于时间的还是其他类型的依赖项)都应该存储在配置文件中这样就可以进行更改并轻松地测量性能我还建议您指定默认缓存持续时间而且如果没有为所使用的 cacheKey 指定持续时间就让 GetCacheSecondsFromConfig() 方法使用该默认持续时间
相关的代码示例是一个 helper 类它将处理上述所有情况但允许通过一行或两行代码访问缓存的数据请下载 CacheDemosmsi
小结
缓存可以使应用程序的性能得到很大的提高因此在设计应用程序以及对应用程序进行性能测试时应该予以考虑应用程序总会或多或少地受益于缓存当然有些应用程序比其他应用程序更适合使用缓存对 ASPNET 提供的缓存选项的深刻理解是任何 ASPNET 开发人员应该掌握的重要技巧
尽早缓存经常缓存
您应该在应用程序的每一层都实现缓存向数据层业务逻辑层UI 或输出层添加缓存支持内存现在非常便宜 — 因此通过以智能的方式在整个应用程序中实现缓存可以获得很大的性能提高
缓存可以掩盖许多过失
缓存是一种无需大量时间和分析就可以获得足够良好的性能的方法这里再次强调内存现在非常便宜因此如果您能通过将输出缓存 秒而不是花上一整天甚至一周的时间尝试优化代码或数据库就可以获得所需的性能您肯定会选择缓存解决方案(假设可以接受 秒的旧数据)缓存正是那些利用 % 付出获得 % 回报的特性之一因此要提高性能应该首先想到缓存不过如果设计很糟糕最终却有可能带来不良的后果因此您当然也应该尽量正确地设计应用程序但如果您只是需要立即获得足够高的性能缓存就是您的最佳选择您可以在以后有时间的时候再尽快重新设计应用程序
页面级输出缓存
作为最简单的缓存形式输出缓存只是在内存中保留为响应请求而发送的 HTML 的副本其后再有请求时将提供缓存的输出直到缓存到期这样性能有可能得到很大的提高(取决于需要多少开销来创建原始页面输出 发送缓存的输出总是很快并且比较稳定)
[] []