如何使用服务器缓存?如何实现服务器缓存?
一、上章回顾
上一章中我们主要简单的介绍了如何使用服务器缓存及如何实现服务器缓存,下面我们来通过下图来进行详细回顾:
1、用户发送页面请求,等待服务器返回信息。
2、表示层通过请求业务层来访问业务数据信息。
3、业务层在与数据访问层交互时先与服务器缓存组件交互。
4、服务器缓存在接收数据请求并处理的过程中判定服务器缓存中是否存在指定的数据集缓存对象。如果存在则返回该缓存对象,否则通过数据访问层,访问数据库中的数据,并把数据缓存在服务器组件中。并返回该查询结果集。
5、表示层获得数据集合后显示。
二、摘要
本章将主要讲解缓存中的过期策略及如何平衡过期这个过期策略,怎么样在项目中解决这样的问题,这就是本篇要讲述的内容。
三、本章大纲
1、上章回顾。
2、摘要。
3、本章大纲。
4、具体策略分析。
5、缓存过期策略方案。
6、本章总结。
7、下篇预告。
四、具体策略分析
我们我们平时使用缓存中最头疼的问题应该就是缓存的过期的问题吧,缓存带来的好处显而易见,不见提高了网站应用程序的性能,同时提高了访问的速度,减少了与数据库交互的次数。无疑是好的方案,所以网上有很多的建议都是,能缓存的数据尽量缓存,因为缓存必定能带来性能的提升。同时有个很大的问题始终困扰着我们。这样是我平时在使用缓存的过程中头疼的问题。例如这样的情况:
所以问题就随之而来,如何保证这个产品策略的过期性和同步性,当然我们知道产品分类一般情况下变化不大,所以我们缓存,对于信息变化或者改变频率较高的数据,我们当然可以考虑每次加载的时候都缓存,等到第二次访问的时候过期这样的方式来处理也是可以的。总之呢就是不经常改变的常用的数据信息能缓存的一定缓存。大家都知道2-8法则的,其实不管是什么程序基本上都满足这个原则。
当然Winform的程序则会比较复杂一些,可能制定的策略相对来说也不好指定。因为一般情况下来说客户端/服务器这样的形式,一般的数据信息都缓存在客户端,这样服务器压力小一些,当然也有弊端,就是每个客户端都是有自己的快照副本,不过由于现在硬件的速度发展迅速,所以这方面的力度可以考虑加大,显而易见,当数据库中的数据发生改变后,如何通知winform程序进行缓存更新也是个重要的问题,毕竟winform程序的缓存策略与web程序的缓存方式有所不同。当然如果说winform也是采用服务器端缓存的话,当然也可以采用上面我们讨论的方式来实现更新策略。
下面我们来看看我理解的可操作的winform的缓存策略的更新。
当然上面只是个人愚见,不足之处还请大家多多指点。欢迎大家拍砖,下面我们来讲讲各种策略的实现及优缺点。
五、缓存过期策略方案
上面我们简单的分析了,winform与web应用程序的可能的缓存过期策略。下面我们来讲讲几种可能的解决方案,当然只是个人愚见,还请大家拍砖,这里只是抛砖引玉,没有考虑更复杂的情况。还请大家多多分享自己的经验。
1、使用微软提供的服务器缓存的过期策略:
a、相对过期。举个简单例子就是,如果缓存对象在某个时间段内没有被访问过,那么该对象则过期,否则则不过期。
b、绝对过期。举个简单例子就是,不管缓存的对象访问没有访问过,只要到达设置的时间则过期。
具体的实现时,我们可以参考通过配置文件中设置这个过期策略,例如我们参考IBatisNet中的缓存
1 <cacheModels>//缓存的对象列表
2 <cacheModel id="CacheLRU_Sys_UserRole" implementation="LRU" >//缓存的对象
3 <flushInterval minutes="2" />//设置过期策略
4 <flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的动作
5 <flushOnExecute statement="Update_Sys_UserRole"/>
6 <flushOnExecute statement="Delete_Sys_UserRole"/>
7 <property name="CacheSize" value="100"/>//设置缓存对象的大小
8 </cacheModel>
9 </cacheModels>
显然通过上面提供的方式可以做到缓存对象的自动过期,但是有个情况就是不够灵活,如果缓存对象在指定的时间段内已发生改变,那么必须在过期时间后才能更新缓存对象,那么有些时候显然不能满足我的要求,特别是实时性的系统时这样的缓存策略是不可行的。
2、当然上面介绍的IBatisNet中已包含设置刷新对象时的操作的设置:
1 <flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的动作
2 <flushOnExecute statement="Update_Sys_UserRole"/>
3 <flushOnExecute statement="Delete_Sys_UserRole"/>
那么体现在程序中的代码如何书写呢,我们来看看。
01 /// <summary>
02 /// 定义委托、用于指向更新缓存的事件
03 /// </summary>
04 /// <returns>返回是否更新缓存</returns>
05 public delegate bool RefreshCache(object sender, EventArgs e);
06
07 /// <summary>
08 /// 维护缓存更新策略的委托集合
09 /// </summary>
10 public Dictionary<object, List<RefreshCache>> list;
那么通过XML配置相关的引发缓存更新的事件来达到更新缓存的目的。
那么每次委托列表中维护的对象即是所有的缓存对象的相关刷新动作事件。通过检测事件的执行来更新缓存对象。
具体的更新缓存的代码如下:
1 public void RefreshCacheObject(object key,bool isSuccess)
2 {
3 if (!isSuccess)
4 return;
5 if (list.ContainsKey(key))
6 list.Remove(key);
7
8 //载入缓存
9 }
具体的载入缓存的代码请参考:网站性能优化之应用程序缓存-初篇
具体的实现底层通知的代码我还没有想好具体的实现方式(就是比较好的方式)。想好了会把代码贴上,当然IBatisNet已经很优秀了,我这里也许没有造轮子的必要,如果谁有比较好的实现方式,那么可以告诉我,我这里先谢过了,我其实不是很了解底层的实现机制,所以我目前只是采用比较笨的方式来做,虽然也实现了,但是需要在每个事件中都要显示的写一部分代码,这是我不能接受的。
3、时时更新的方式。
这里的时时更新就是指,每次都把数据库中的记录全部取出来,然后循环比较结果集中的记录与缓存的记录是不是相同,如果不同则更新该记录,否则跳过继续处理其他的数据信息,那么保证缓存中的记录始终是最新的。当然这样的方式虽然保证所有的缓存信息是最新的,但是每次都与数据库交互显然不是好的解决方案,当然有些情况下也许也是没有办法的事情。
最后,本文只是抛砖引玉,希望大家多多提出宝贵意见。
六、本章总结
本文简单的介绍了web与winform下的缓存策略,分析了几种方式的可行性及优缺点等,还希望大家在实际的项目中根据项目的需要来指定缓存的过期策略,但是可以肯定的是,用缓存肯定比不用缓存的性能要高。当然这里也不是要求我们滥用缓存,也要根据数据信息的更新频度做一个平衡,不经常变的数据一般推荐来缓存。毕竟服务器中有同一副本,不但能提高访问的效率,还能减轻数据库的访问压力,提高并发的速度。还需要大家在实际项目中体会。
七、下篇预告
本篇并没有把IBatis.NET中的缓存策略完整的实现,并且也没有讲到其他的一些winform的缓存策略的实现,下一篇将会详细的讲解这部分的内容,当然这些都是本人的个人体会与总结,错误之处在所难免,欢迎大家提出不同意见,批评指出错误,谢谢大家!