配置和使用Ehcache

一、介绍 

  网上有很多关于Ehcache的介绍,这里就不在多说了,只需要知道Ehcache是一个缓存框架。缓存嘛,就是数据存取比硬盘快,但是容量小的存储区域。当我们需要频繁使用某些数据时,我们可以将这些数据放到缓存中,下次取数据的时候,直接从缓存中取,这样可以节省不少时间。如果我们自己手动进行缓存的管理将是比较棘手的的,因为这已经涉及到很多底层的技术了,但是Ehcache为我们做了封装,我们可以很方便地使用Ehcache来进行缓存的管理。

  Ehcache可以保存Element对象,这个Element对象本质上是一个key-value的键值对,其中key和value可以使是任意数据类型,这就代表可以用Ehcache来缓存任何类型的数据。

  下面将单独Ehcache的配置和使用方式,如果想要看Ehcache和Spring的整合,可以查看:

二、导入jar包

  我这里使用的是Ehcache2.10.6这个版本,虽然最新的Ehcache已经发布了3.7,根据情况选择版本;

  如果是Maven项目,可以在pom.xml中添加下面的依赖:

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.6</version>
</dependency>

  我这里创建的是Java Web项目,所以使用手动导入jar包的方式创建项目。

三、XML方式配置Ehcache

  创建一个XML文件,文件名和保存路径随意(只要你能找到就行)。

  我这里是在项目的resources下创建一个ehcache.xml文件,内容如下,现在可以不用深究每一项配置的用途(其实看名称也能大概猜到用途):

<?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="/home/ganlixin/tmp" />

	<cache name="cacheOne" 
		maxBytesLocalDisk="5g" maxBytesLocalHeap="20m" maxBytesLocalOffHeap="200m"
		maxEntriesLocalHeap="200" maxEntriesLocalDisk="300"
		maxEntriesInCache="500" maxElementsInMemory="1000" eternal="false"
		timeToIdleSeconds="60" timeToLiveSeconds="60" overflowToDisk="true"
		memoryStoreEvictionPolicy="LRU">
	</cache>

	<cache name="cacheTwo" 
		maxBytesLocalDisk="5g" maxBytesLocalHeap="20m" maxBytesLocalOffHeap="200m"
		maxEntriesLocalHeap="200" maxEntriesLocalDisk="300"
		maxEntriesInCache="500" maxElementsInMemory="1000" eternal="false"
		timeToIdleSeconds="60" timeToLiveSeconds="60" overflowToDisk="true"
		memoryStoreEvictionPolicy="FIFO">
	</cache>
</ehcache>

  我们上面创建的ehcache.xml配置文件相当于配置了三个“桶”,名称分别是defaultCache、cacheOne、cacheTwo,每一个桶都是一个缓存区域,我们可以将数据放入桶中,实现了数据的缓存。

  我们可以创建多个ehcache配置文件,每一个配置文件可以理解为下面这张图。

  在缓存数据之前,我们可以自己选择读取哪个ehcache的配置文件(读取不同的配置文件,创建的缓存区域是不一样的),然后根据自己的需求,将数据放入我们指定的桶中。

  

四、测试使用Ehcache

  上面将ehcache配置好后,就可以进行测试了: 

package cn.ganlixin.test;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class Demo {

	public static void main(String[] args) {
		
		// 读取ehcache配置文件,创建cacheManager
		CacheManager cacheManager = CacheManager.create("ehcache.xml");
		
		// 利用cacheManager获取指定的cache(相当于指定使用哪个桶来保存数据)
		// 如果不指定的话,就会使用默认的defaultCache来存数据
		Cache cache = cacheManager.getCache("cacheOne");

		// 创建Element,Element是一个key-value形式的,key和value可以是任意数据类型
		Element e = new Element("keyOne", "valueOne");
		
		// 将Element放入我们指定的缓存中(也就是cacheOne那个桶中)
		cache.put(e);

		// 通过传入key值,从cache中获得Element
		Element e2 = cache.get("keyOne");
		System.out.println(e2);
		// 获取的Element对象包含多个属性,打印的结果如下:
		// [ key = keyOne, value=valueOne, version=1, hitCount=1, CreationTime = 1558015329449, LastAccessTime = 1558015329451 ]
		
		// 可以单独的获取Element属性
		System.out.println(e2.getObjectKey());
		System.out.println(e2.getObjectValue());
		System.out.println(e2.getVersion());
		System.out.println(e2.getHitCount());
		System.out.println(e2.getCreationTime());
		System.out.println(e2.getLastAccessTime());
		System.out.println(e2.getExpirationTime());
		
		// 移除指定cache中的key对应的Element,移除成功则返回true,如果不存在或者Element已经过期,则返回false
		// 注意移除不存在Element,并不会报错
		boolean isRemoved = cache.remove("keyOne");
		
		// 替换
		Element e3 = cache.replace(e2); // 返回替换前的Element,如果不存在则返回null
		boolean isReplaced = cache.replace(e2, e3);
		
		// 关闭cacheManager
		cacheManager.shutdown();
	}
}

  

五、Ehcache的数据存储

  对于Ehcache来说,缓存的数据可以保存自两个地方:内存和磁盘。其中数据存储内存是始终启用的,但是磁盘存储却并没有强制要求,可以自己配置。

  对于内存来说,还可以细分,Ehcache将内存分了两类:堆内存和非堆内存。 对于这两类,Ehcache官网是这样描述的:

The memory store is always enabled and exists in heap memory. For the best performance, allot as much heap memory as possible without triggering garbage collection (GC) pauses, and use the off-heap store to hold the data that cannot fit in heap (without causing GC pauses).

  翻译过来就是说:尽量扩大堆的容量(保证不会因为堆的容量不足而发生GC,导致停顿),并且尽量将不适合用堆来存储的数据放入非堆内存的区域进行存储。

六、配置文件解析

  Ehcache默认的是去项目的类路径(也就是classpath)目录下寻找ehcache.xml文件作为Ehcache的配置文件,但是我们也可以自己指定配置文件的名称和路径,只需要在创建CacheManager的时候保证自己写的路径没有错误即可。

  首先知道的是,Ehcache不仅支持我们在XML配置文件中对Ehcache进行配置,同时还支持我们在代码中进行Ehcache的配置(比如创建一个新的cache),但是,好像没有人会这样做,因为一旦将配置写在Java代码中,一旦要修改配置,就需要重新编译一次源码(甚至需要重新编译整个项目),而写在XML中就没有这个问题,只需要重新启动项目即可。

  我这里将ehcache.xml分为三部分,然后详细介绍每一部分。

6.1、CacheManager级别

<?xml version="1.0" encoding="UTF-8"?>
<ehcache 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
	
	maxEntriesLocalHeap="2000"
	maxEntriesLocalOffHeap="2000"
	maxEntriesLocalDisk="3000"
	
	maxBytesLocalDisk="5g" 
	maxBytesLocalHeap="20m"
	maxBytesLocalOffHeap="200m"
	
	memoryStoreEvictionPolicy="LRU"
>
</ehcache>

  maxEntriesLocalHeap属性:在堆中,允许存放的Element最大数量值。

  maxEntriesLocalOffHeap属性:在堆外的内存中允许存放的Element的最大数量值。

  maxEntriesLocalDisk属性:在磁盘上允许存放的Element的最大数量值,如果设置为0,表示数量没有限制(可能会出现磁盘全部用尽的情况)。

  maxBytesLocalDisk属性:指定Ehcache可以在磁盘上占用的空间大小。

  maxBytesLocalHeap属性:制定Ehcache可以在堆内存中占用的空间大小。

  maxBytesLocalOffHeap属性:指定Ehcache可以在堆外的内存中占用多大的大小。

  memoryStoreEvictionPolicy属性:指定回收策略,可以选择:LRU、FIFO、LFU。

  上面的这几个属性不仅可以在CacheManager级别配置,还可以在<cache>配置。不过需要注意的是:如果CacheManager级别配置了maxBytesLocalDisk、maxBytesLocalHeap、maxBytesLocalOffHeap这几个属性,那么他下面的每个<cache>也必须配置这些属性,并且<cache>中配置的空间是从CacheManager中扣除的。

6.2、diskStore

<?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="/home/ganlixin/tmp" />

</ehcache>

  <diskStore>可以用来配置是否启用磁盘存储,并指定保存的路径。如果启用磁盘存储的话,可以配置当内存中的Element超出限制时,将缓存中的数据写到磁盘中。

6.3、cache级别

<cache name="cacheOne" 
	maxBytesLocalDisk="5g" 
	maxBytesLocalHeap="20m"
	maxBytesLocalOffHeap="200m"
	
	maxEntriesLocalHeap="2000"
	maxEntriesLocalDisk="3000"
	
	maxEntriesInCache="500"
	maxElementsInMemory="1000"
	
	eternal="false"
	
	timeToIdleSeconds="60" 
	timeToLiveSeconds="60"
	
	overflowToDisk="true"
	memoryStoreEvictionPolicy="LRU"
>
	<persistence strategy="localTempSwap"/>
</cache>

  这一部分的很多属性都和CacheManager级别的属性相同,但是注意<cache>中不能出现MaxEntriesLocalOffHeap,也就是说不能配置堆外内存的大小。

  timeToIdleSeconds属性:元素放入cache后,距离上一次被访问的时间超过timeToIdleSeconds秒,元素就会被清除。如果设置为0,则表示距离上一次被访问的时间超过timeToIdleSeconds秒,元素也不会被清除。

  timeToLiveSeconds属性:距离该元素放入cache时间超过了timeToLiveSeconds秒,元素就会被清除,及时在此此件被访问过多次,依旧会被清除。如果设置为0,则表示即使距离放入元素的时间超过timeToLiveSeconds秒,元素也不会被清除。

  eternal属性:是否设置元素的生命周期为无限。如果设置为true,则表示即使超过设置的timeToIdleSeconds或者timeToLiveSeconds,元素也不会内清除(此时timeToIdleSeconds和timeToLiveSeconds相当于设置为0)。

  overflowToDisk属性:当内存中已经存放不下元素的时候(设置的内存大小不足),是否选择将元素保存到磁盘中。

  memoryStoreEvictionPolicy属性:cache中元素的回收策略。

  <persistence strategy="localTempSwap" /> 表示使用cache期间,会使用本地的磁盘交换空间,但是存在这上面的数据并不能真正持久化(一旦重启就消失了)。

   

七、与Spring框架的整合

  这个可以参考:Spring整合Ehcache

原文地址:https://www.cnblogs.com/-beyond/p/10878434.html