1.前言
今天在学习Ehcache相关的知识,前面写配置文件以及简单测试类的时候还是一帆风顺的~
直到我碰到Ehcache的磁盘持久化机制
2.相关配置
我依赖的jar包版本是下面这个
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.2</version>
</dependency>
参照网上的资料编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir/ehcache"/>
<!-- 默认缓存 -->
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!-- helloworld缓存 -->
<cache name="HelloWorldCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="50000"
timeToLiveSeconds="50000"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
下面就说下我遇到的几个“坑”
3.overflowToDisk
首先是overflowToDisk这个属性,这个属性我一开始的理解是设置为true后,当内存中缓存的对象大于maxElementsInMemory的数值,他就会自动将我们在内存中缓存的对象序列化到我配置的磁盘路径(缓存的对象已经实现序列化接口)。
但其实不然,描述下我测试这个过程的整个步骤
一、我编写了一个测试类如下
@Test
public void test() throws IOException {
//绑定资源路径
CacheManager cacheManager=CacheManager.create(Resources.getResourceAsStream("ehcache.xml"));
//获取cache
Cache cache = cacheManager.getCache("HelloWorldCache");
Person person = new Person("a",1);
Person person2 = new Person("b",2);
Person person3 = new Person("c",3);
//新建两个Element对象
Element element = new Element("person", person);
Element element2 = new Element("person2", person2);
Element element3 = new Element("person3", person2);
//将元素添加到缓存
cache.put(element);
cache.put(element2);
cache.put(element3);
System.out.println(cache.get("person"));
System.out.println(cache.get("person2"));
System.out.println(cache.get("person3"));
System.out.println(cache.getSize());
cacheManager.shutdown();
}
二、为了验证ehcache的磁盘序列化,我先尝试将maxElementsInMemory的数值等于1,然后再运行上述的代码,得到的结果是
这个结果也在预料之中,按照配置的清除策略,最先被创建的对象会被清除,然后我尝试将overflowToDisk修改为true,我的认为的结果是ehcache会将超出的对象序列化到我配置的磁盘路径,但结果不然
三个对象的确都打印出来了,但是我在配置文件所配置的磁盘路径下的文件夹却是空空如也~
难道ehcache欺骗了我!但是我也在控制台输出了和之前不一样的结果,说明这个属性的配置的确改变了什么
三、在思考过后我决定前往默认的磁盘缓存目录下一探究竟,终于让我发现,确实某些文件被创建了出来
具体原理以及过程我不是很确定,以我自己的理解:我觉得ehcache的确将超出的对象进行了序列化,并且放在了上述的目录中
4.diskPersistent
该属性是用于在JVM重启时将加载在硬盘的缓存数据,本来是个非常容易懂得概念,但是在实操的时候我发现了一些“状况”
一、在配置该属性为true后,我马上重新启动我的测试类,但不一样的是,我将三行代码注释了
因为我认为ehcache已经帮我把这些数据序列化到磁盘上了,所以我认为是可以直接得到这三个对象的,但结果不然 ,我得到了三个空指针
二、于是我又将三行注释打开,再执行了一遍程序
这次在我配置的磁盘目录下出现了数据,然后当我再次将上面三行代码注释重新执行程序
终于得到了我如愿以偿的结果
5.总结
- 没有配置overflowToDisk属性前,达到最大缓存对象数目(即maxElementsInMemory后),ehcache会根据策略清理缓存,但是配置overflowToDisk属性后,缓存会得到保留,个人认为他是将缓存保存到磁盘上(但不是自己配置的目录,而是他的一个默认目录)
- 想要将缓存持久化到磁盘,并且关闭服务器后下次打开可以继续使用上次的缓存,则必须要配置diskPersistent属性为true,才会将数据持久化到你配置的路径文件夹中(甚至不需要配置overflowToDisk)
- 缓存要想持久化,一定要执行cacheManager.shutdown()这条语句,否则强行中断程序或者不写(只写flush也不行)都是没办法序列化数据的(建议配置个监听器)