版权声明:如有转载请求,请注明出处:http://blog.youkuaiyun.com/yzhz 杨争
Cache is King
Cache is King这句话说明了Cache在一个系统中对于提高系统性能的重要性。从硬件CPU到操作系统,从系统软件到应用软件,我们到处都可以看到Cache的身影。
对于基于J2EE的网站,如何使用好Cache成为我们网站实现高性能的关键。同时Cache的不恰当使用以及在使用Cache中没有注意到某些环节,会给我们的系统埋下隐患,说不准什么时候这个定时炸弹就会爆炸。所以开发人员要时刻牢记要让Cache成为我们系统优化的有利武器,而不是噩梦。
本人根据多年在开发部署中使用Cache的情况,总结了以下Cache使用的经验:
1、什么样的数据适合放入Cache中?
任何数据放入Cache中都要考核这些数据是否符合这三个指标(更新频率、访问量、命中率)。我们要把更新不频繁,访问量高,命中率高的数据放入Cache中。
通常这三个指标在系统设计的时候我们基本上就能确定我们要取的数据是否符合。唯一存在疑问是命中率指标,这时候我们可以在Cache系统中添加统计Cache的命中率模块,以便确定该Cache命中的有效性。
这三个指标的考核是AND的关系,只有同时满足,才最有效果。比如某种数据访问频率很高,但需要时时更新,这种数据就不适合放入Cache中。当然还有一种情况,我们常常会把某些特别费数据库性能的数据放入Cache,尽管这批数据可能访问量不高。
2、Cache使用中要注意哪些问题。
我觉得最重要的就是线程安全问题。由于Cache的引入,实际上引入了一个共享区域,对这块共享区域的访问要特别注意。
我们看看会有哪些问题?
(1)、如果Cache中放入HashMap对象,由于HashMap类是没有做同步的,所以在多线程的情况下如果出现其中一个线程增加或者修改该list的元素,则会出错,这时候我们需要对HashMap的访问synchronized.
见HashMap的jdk说明:http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/util/HashMap.html
(2)、当Cache中放入Collection对象,同时程序使用迭代器Iterator来访问该集合对象。如果在一个线程正在通过一个 Iterator 遍历集合时,另一个线程也来修改这个集合,那么接下来的 Iterator.hasNext() 或 Iterator.next() 调用将抛出 ConcurrentModificationException 异常。因此,多线程中使用迭代器iterstor要特别小心。
3、Cache实现的方式。
Cache的实现方式可以是集中式Cache和分布式Cache,各自都有其特点,适用于不同的情况。分布式Cache目前成熟的解决方案之一是通过jgroup实现内存cache的同步。
Cache的载体可以是内存、磁盘文件、数据库。具体采用哪种方式需要我们根据应用的实际情况而定。
现在的Cache产品有很多可供我们选择,当然我们自己也可以设计,最简单可以是一个HashMap就行。
不管怎么样,我觉得使用Cache的原则就是:越简单越适合我们要求的越好。