EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试.官方网站http://ehcache.sourceforge.net/
毫无疑问,几乎所有的网站的首页都是访问率最高的,而首页上的数据来源又是非常广泛的,大多数来自不同的对象,而且有可能来自不同的db ,所以给首页做缓存是一个不错的主意,那么主页的缓存策略是什么样子的呢,我认为应该是某个固定时间之内不变的,比如说2 分钟更新一次.那么这个缓存应该做在什么地方呢,让我们来看一下,假设您的应用的结构是page-filter-action-service-dao-db ,这个过程中的- 的地方都是可以做缓存的地方,根据页面缓存的特征,应该把页面缓存做到尽量靠近客户的地方,就是在page 和filter 之间,这样的优点就是第一个用户请求之后,页面被缓存,第二个用户再来请求的时候,走到filter 这个请求就结束了,无需再走后面的action-service-dao-db .带来的好处是服务器压力的减低和客户段页面响应速度的加快.
那么我们来看一下如何使用ehcache 做到这一点.
在使用ehcache 的页面缓存之前,我们必须要了解ehcache 的几个概念,
1 timeToIdleSeconds ,多长时间不访问该缓存,那么ehcache 就会清除该缓存.
2 timeToLiveSeconds ,缓存的存活时间,从开始创建的时间算起.
首页的页面缓存的存活时间,我们定的是2 分钟,timeToLiveSeconds 应该设置为120 ,同时我们的timeToIdleSeconds 最好也设置为2 分钟,或者小于2 分钟.我们来看一下下面这个配置,这个配置片段应该放到ehcache.xml 中:
<cache name= "SimplePageCachingFilter"
maxElementsInMemory = "10"
maxElementsOnDisk = "10"
eternal = "false"
overflowToDisk = "true"
diskSpoolBufferSizeMB = "20"
timeToIdleSeconds = "10"
timeToLiveSeconds = "10"
memoryStoreEvictionPolicy = "LFU"
/>
SimplePageCachingFilter 是缓存的名字,maxElementsInMemory 表示内存中SimplePageCachingFilter 缓存中元素的最大数量为10 ,maxElementsOnDisk 是指持久化该缓存的元素到硬盘上的最大数量也为10 ,eternal=false 意味着该缓存会死亡.overflowToDisk=true 意思是表示当缓存中元素的数量超过限制时,就把这些元素持久化到硬盘,如果overflowToDisk 是false ,那么maxElementsOnDisk 的设置就没有什么意义了.memoryStoreEvictionPolicy=LFU 是指按照缓存的hit 值来清除,也就是说缓存满了之后,新的对象需要缓存时,将会将缓存中hit 值最小的对象清除出缓存,给新的对象腾出地方来了(文章最后有ehcache 中自带的3 种缓存清空策略的介绍).
SimplePageCachingFilter 的配置,
<filter>
<filter-name> indexCacheFilter </filter-name>
<filter-class>
net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name> indexCacheFilter </filter-name>
<url-pattern> *index.action </url-pattern>
</filter-mapping>
就只需要这么多步骤,我们就可以给某个页面做一个缓存的,把上面这段配置放到你的web.xml 中,那么当你打开首页的时候,你会发现,2 分钟才会有一堆sql 语句出现在控制台上.当然你也可以调成5 分钟,总之一切都在控制中.
好了,缓存整个页面看上去是非常的简单,甚至都不需要写一行代码,只需要几行配置就行了,够简单吧,虽然看上去简单,但是事实上内部实现却不简单哦,有兴趣的话,大家可以看看SimplePageCachingFilter 继承体系的源代码.
上面的配置针对的情况是缓存首页的全部,如果你只想缓存首页的部分内容时,你需要使用SimplePageFragmentCachingFilter 这个filter .我们看一下如下片断:
<filter>
<filter-name> indexCacheFilter </filter-name>
<filter-class>
net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name> indexCacheFilter filter-name>
<url-pattern> */index_right.jsp </url-pattern>
</filter-mapping >
这个jsp 需要被jsp:include 到其他页面,这样就做到的局部页面的缓存.这一点貌似没有oscache 的tag 好用.
事实上在cachefilter 中还有一个特性,就是gzip ,也就是说缓存中的元素是被压缩过的,如果客户浏览器支持压缩的话,filter 会直接返回压缩过的流,这样节省了带宽,把解压的工作交给了客户浏览器,如果客户的浏览器不支持gzip ,那么filter 会把缓存的元素拿出来解压后再返回给客户浏览器(大多数爬虫是不支持gzip 的,所以filter 也会解压后再返回流),这样做的优点是节省带宽,缺点就是增加了客户浏览器的负担(但是我觉得对当代的计算机而言,这个负担微乎其微).
好了,如果你的页面正好也需要用到页面缓存,不防可以考虑一下ehcache ,因为它实在是非常简单,而且易用.
总结:ehcache 是一个非常轻量级的缓存实现,而且从1.2 之后就支持了集群,目前的最新版本是1.3 ,而且是hibernate 默认的缓存provider .虽然本文是介绍的是ehcache 对页面缓存的支持,但是ehcache 的功能远不止如此,当然要使用好缓存,对JEE 中缓存的原理,使用范围,适用场景等等都需要有比较深刻的理解,这样才能用好缓存,用对缓存.
ehcache 中缓存的3 种清空策略:
1 FIFO ,first in first out ,这个是大家最熟的,先进先出,不多讲了
2 LFU , Less Frequently Used ,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的.如上面所讲,缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存.
2 LRU ,Least Recently Used ,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存.
简介
Ehcache俩中缓存机制:
· MemoryStore(内存存储)
· DiskStore(磁盘存储)
MemoryStore
MemoryStore总是可用的,但不可直接操作,当中存储着所有的Cache.
· 合适的Element类型
所有的Element都可以放在MemoryStore中.
· 安全性:使用多个线程并行检查内存泄露.
· JDK:使用了JDK1.5的LinkedHashMap来存放Elemen.t
· 快速的:是最快的缓存机制,因为它是存放在内存中.
· 失效策略(Memory)
Cache 可以配置最大缓存Element的个数,以及失效时间.如果在添加Elemtent时,缓存中的Element个数达到了最大缓存数并且 overflowToDisk配置的属性为true,Ehcache会更具配置项MemoryStoreEvictionPolicy的失效策略将 Element输出到磁盘.如果overflowToDisk为fasle,Ehcache将删除内存中Element.Ehcache支持三种失效策略:LRU,LFU,FIFO.
值得注意的是缓存中失效的Element并不会别马上清理掉,所以想得到内存的真实大小应该调用方法calculateInMemorySize()方法.
DiskStore
DiskStore可缓存到外部设备上(硬盘).
· DiskStores are Optional
Ehcache从1.5版本开始支持DiskStore.如果你需要多个DiskStore的话,最好给他们配置不同的文件路径.
· 关闭磁盘缓存:只要注释掉ehcache.xml配置文件中的磁盘缓存配置项即可.而ehcache-failsafe.xml的磁盘缓存配置不会影响到你自己的cache.
· 合适的Element类型
这里要注意要想使用磁盘缓存,缓存的Element必须实现序列化接口.否则会抛出NotSerializableException异常.
· 存储:Ehcache会将每个缓存配置的文件路径下创建一个cache_name.data文件,如果使用的磁盘持久化技术,还会生成一个cache name.index文件.
· 失效
Ehcache有一个后台线程专门做Ellment失效监测以及清除工作.设置线程运行间隔时间,可通过设置diskExpiryThreadIntervalSeconds属性来完成,此值不宜设置过低,否则会导致清理线程占用大量CPU资源.默认值是120秒.
· 持久化
持久化可在Element的diskPersistent配置项中配置,如果配置为"false"或是"omitted"在CacheManager shutdown或是startup后,用来缓存Element的文件将被清除掉.如果设置为"true",data和index文件会被保存下来,对于新创建的CacheManager Element也是可用的.
使用时必须显示调用cache. Flush()才会将数据缓存到磁盘中.
磁盘缓存步骤:从MemoryStore中把没有失效的Element刷新到DiskStore,Element被写入到data文件,Element将被序列化到index文件.
Ehcache缓存回收策略
缓存回收就是当缓存满了的时候,Ehcache会根据指定的策略来清理缓存.这里的缓存回收策略有别与Ehcache中的失效清理策略.失效清理策略是对失效的Element进行批量清理时所采用的策略,最终所有失效的Element都将被清理,只不过是清理的先后顺序不同罢了.Ehcache中缓存的最大 Element数是由maxElementsInMemory来指定的.当缓存中的Element个数达到maxElementsInMemory指定的值时,Ehcache会根据具体的策略来清理缓存,默认的策略是LRU(最近最少使用).
磁盘缓存大小默认是没有限制的,不过可通过maxElementsOnDisk来指定.当磁盘缓存达到maxElementsOnDisk指定的值时,Ehcache会清理磁盘中的缓存使用默认策略是LFU(使用频率最低).
Make sure you are using a supported Java version.
Place the Ehcache jar into your classpath.
Ensure that any libraries required to satisfy dependencies are also in the classpath.
Configure ehcache.xml and place it in your classpath.
Optionally, configure an appropriate logging level.
Downloads: http://sourceforge.net/projects/ehcache/files/
Welcome to ehcache:http://ehcache.org/