带你走进缓存世界(2):缓存入门
昨天在群里有个朋友问,如何使用数据库的临时表。问其原因,原来是他想把查询的结果导出excel,但是苦于查询结果是100个里面随机挑出50个,所以他想把查询结果放在临时表里,导出的时候查询临时表。这个方法不是不可取,其实更好的办法就是把查询的结果DataTable,放到缓存里,导出的时候直接使用就行了。然后群里的同学们都纷纷表明如何使用缓存。
本次我们就讲下.Net Framework自带的缓存类,这也算是走进缓存使用的大门了。
Web开发中,常用的两个缓存对象是HttpContext.Cache和HttpRuntime.Cache,这两个对象的类型都是System.Web.Caching.Cache类。区别是一个是当前上下文的cache一个是运行时cache,他俩的区别大家可以搜索下,我们这里只说怎么使用Cache类,其实他们俩没啥区别,就web开发而言。
MSDN上有Cache类的详细介绍http://msdn.microsoft.com/zh-cn/library/system.web.caching.cache.aspx,大家可以打开看看:
void Insert(string key,Object value)
这个方法是最常用的方法之一,就是向Cache里增加一个缓存(key,value),如果Cache里有就替换,没有就是插入。
void Insert(string key,Object value,CacheDependency dependencies)
此方法和上面的类似,但是多了一个缓存依赖项参数,当依赖的内容改变时,缓存就被移除掉了,也就是无法获取缓存了。
void Insert(string key,Object value,CacheDependency dependencies,DateTime absoluteExpiration,TimeSpan slidingExpiration)
这个方法相比上面的又增加了2个时间参数,第一个是具体的到期时间,第二个则是缓存最后使用时间和过期时间的时间差。 如果DateTime指定了具体的时间,则TimeSpan就为Cache.NoSlidingExpiration(此类型是TimeSpan,值为TimeSpan.Zero),如果TimeSpan指定了20分钟,则DateTime就为Cache.NoAbsoluteExpiration(此类型是DateTime,具体值是DateTime.MaxValue),每次使用缓存,过期时间就会推迟20分钟。
void Insert(string key,Object value,CacheDependency dependencies,DateTime absoluteExpiration,TimeSpan slidingExpiration,CacheItemPriority priority,CacheItemRemovedCallback onRemoveCallback)
CacheItemPriority参数是个枚举类型,从名字可以看出该值是优先级的意思,也就是优先移除比较低的缓存,该方法又多了个Callback方法参数(即委托),也就是当缓存过期时会执行该方法。
Object Remove(string key)
移除缓存,并且厚道的返回了这个缓存的值,如果没有缓存则返回null
大致介绍了下几个方法,了解他们之间的区别在于缓存的移除策略(依赖项、时间、优先级、回调函数)。
依赖项:
比如,我们的站点的配置(config.xml)放入了缓存里,缓存的过期就依赖于config.xml的变动,跟时间没关系。 所以我们可以采第二个Insert方法。
到期时间:
比如,我们首页的文章列表。由于网站首页的访问量一般都比较大,所以不可以每次都去查询数据库,那么我们可以把首页查询的文章列表放入缓存里(或者把第一页的结果放入缓存里),但是由于列表需要更新,我们可以设置他的更新时间为5分钟,这样就可以利用第三个Insert方法,把TimeSpan设置为new TimeSpan(0,5,0)
优先级:
优先级的含义十分明白,但在普通的Web站点还不至于使用到,但如果单独开发一个缓存服务的话,优先级还是比较重要的,在同样的过期时间的缓存里,会优先剔除级别比较低的缓存以释放内存。
回调函数:
缓存被移除之后,为了保证下次还可以使用缓存,回调函数则可以重新加在缓存。 又或者假如我们设计一个延迟更新的功能,把一些零碎的统计(比如浏览次数)放入缓存中,定时更新一次数据库,这样可以减轻数据库的压力,但又怕缓存丢失时更新有所偏差,所以可以用这种回调的方式保证数据的正确性。
以上是本人愚见,有不正之处还望指点。
了解了Cache类,就赶紧试试吧,尝试把你以前的重复查询优化下:)网上也有很多人写好的CacheHelper类,不过他们不会使用全部的Insert的,因为根据缓存数据的策略不同,侧重点也不一样。你不妨写一个自己的Helper类。