EhCache是一个快速的、轻量的、纯Java的进程内缓存框架,是Hibernate默认的CacheProvider,它支持read-only、read/write和nonstrict-read-write缓存,内存和磁盘缓存,并且从1.2之后支持了集群。
Ehcache的分布式缓存有传统的RMI,1.5版本的JGroups,1.6版本的JMS,从 1.7
版本开始,支持五种集群方案,分别是RMI、JGroups、JMS、Terracotta(/ˌterəˈkɒtə/)和EhCache
Server。分布式缓存主要解决集群环境中不同的服务器间的数据的同步问题。
主要特性:
简单、快速、灵活、轻量
提供了内存缓存和磁盘缓存两级缓存
提供了多种缓存策略
缓存数据会在虚拟机重启的过程中写入磁盘
可以通过RMI、可插入API等方式进行分布式缓存
支持动态、运行时缓存配置
支持多缓存管理器实例,以及一个实例的多个缓存区域
支持基于Cache和基于Element的过期策略,每个Cache的存活时间都是可以设置和控制的
具有缓存和缓存管理器的侦听接口
提供Hibernate的缓存实现
缓存级别:
Ehcache提供了三个级别的缓存:
堆内存储(Memory store):
Accepts all data, whether serializable or not.
Fastest storage option.
Thread safe for use by multiple concurrent threads.
Subject to Java GC.
不要求实现序列化接口。速度快,但是容量有限。受GC管理。
堆外存储(Off-heap store):
Limited in size only by available RAM. Not subject to Java GC.
Can store serialized data only.
Provides overflow capacity to the memory store.
只在企业版本的Ehcache中提供,原理是利用nio的DirectByteBuffer来实现,比存储到磁盘上快,而且不受GC的影响,但是必须以字节数组的方式存储,对象在存储过程中进行序列化,读取则进行反序列化操作,它的速度大约比堆内存储慢一个数量级。
磁盘存储(Disk store):
Backs up in-memory data and provides overflow capacity to the other tiers.
Can store serialized data only.
要求实现序列化接口。
主要类:
每个CacheManager管理多个Cache,而每个Cache都以一种类Hash的方式关联多个Element。
net.sf.ehcache.CacheManager:缓存管理器,可以通过多种方式实例化,new、单例模式、URL、InputStream等方式,也可以通过编码配置,所有的配置项均有默认值。
net.sf.ehcache.Cache:存放Element数据,Element可以存储在MemoryStore或者DiskStore中。
net.sf.ehcache.Element:存储在Cache中的的最基本元素。如果需要集群复制或者存储到disk中,则要求放在Element中的对象是可序列化的。Element包含key,value,还有一些访问控制信息如hitcount,对象创建时间、访问时间等。
配置步骤:
在Maven的pom.xml文件中配置依赖:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
</exclusion>
</exclusions>
</dependency>
在hibernate.cfg.xml、hibernate.properties或者application.yml文件中配置:
hibernate.cache.use_second_level_cache: true
hibernate.cache.use_query_cache: true
hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
在Order.hbm.xml文件中配置:
<class name="Order" table="order">
<cache usage="nonstrict-read-write" region="orderCache" include="all"/>
usage属性:指定缓存策略,可选的策略包括transactional(只适用于JTA)、read-only、read-write和nonstrict-read-write。
region属性(可选):指定二级缓存区域名,指定了二级缓存区域名之后就可以在ehcache.xml中配置相应name的自定义缓存了。如果不指定region的属性值,则使用name名为xxx.xxx.xxx.Order的cache,如果不存在与类名匹配的cache,则使用defaultCache。
include属性(可选):all to include all properties, non-lazy to only include non lazy properties (default all). 指定是否缓存延迟加载的对象,all表示缓存所有对象,non-lazy表示不缓存延迟加载的对象。
或者在hibernate.cfg.xml文件中配置:
<class-cache class="xxx.xxx.xxx.Order" usage="nonstrict-read-write"/>
<collection-cache collection="xxx.xxx.xxx.Order.items" usage="nonstrict-read-write"/>
或者在实体类中添加注解:@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Entity
@Table(name = "order")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Data
public class Order implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name", length = 30)
private String name;
@OneToMany(mappedBy = "order", fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)//集合缓存
private Set<Item> items = new HashSet<Item>();
}
@Entity
@Table(name = "item")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Data
public class Item implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name", nullable = false, length = 30)
private String name;
@Column(name = "status", length = 20)
@Enumerated(EnumType.STRING)
private ItemStatus status = ItemStatus.RAW;
@ManyToOne
private DeliveryOrder order;
}
public enum ItemStatus {
RAW,
PROCESSING,
FINISHED
}
在src目录下创建ehcache.xml文件,配置参考官方提供ehcache.xml
设置ehcache.xml文件的ehcache元素属性:
xsi:noNamespaceSchemaLocation=http://www.ehcache.org/ehcache.xsd
然后在IDEA的Settings -> Languages&Frameworks -> Schemas and Dtds添加地址http://www.ehcache.org/ehcache.xsd
或者在src目录下创建ehcache.xsd文件,从官方提供ehcache.xsd拷贝xsd文件,然后设置ehcache.xml文件的ehcache元素属性:
xsi:noNamespaceSchemaLocation="ehcache.xsd"
(注:官方提供的xml或xsd文档一般显示为颜色化的根元素以及子元素。通过点击元素左侧的加号或减号,可以展开或收起元素的结构。如果需查看不带有+
和-
符号的源代码,请从浏览器菜单中选择”查看源”。)
ehcache.xml配置介绍:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
name="CM1"
updateCheck="true"
dynamicConfig="true">
<!--
ehcache元素(net.sf.ehcache.config.Configuration类)的属性:
name(可选):An optional name for the CacheManager.
The name is optional and primarily used for documentation or to distinguish Terracotta clustered cache state.
With Terracotta clustered caches,
a combination of CacheManager name and cache name uniquely identify a particular cache store in the Terracotta clustered memory.
指定CacheManager的名称。
updateCheck(可选):An optional boolean flag specifying whether this CacheManager should check for new versions of Ehcache over the Internet.
If not specified, updateCheck="true".
是否检查版本更新,默认为true。
设置为true时,CacheManager会定期从网上检查当前ehcache是否是最新版本。
monitoring(可选):An optional setting that determines whether the CacheManager should automatically register the SampledCacheMBean with the system MBean server.
Currently, this monitoring is only useful when using Terracotta clustering and using the Terracotta Developer Console.
With the "autodetect" value, the presence of Terracotta clustering will be detected and monitoring, via the Developer Console, will be enabled.
Other allowed values are "on" and "off". The default is "autodetect". This setting does not perform any function when used with JMX monitors.
dynamicConfig(可选):An optional setting that can be used to disable dynamic configuration of caches associated with this CacheManager.
By default this is set to true
是否可以动态更新配置,默认为true。
设置为false时,在运行期通过CacheManager的Configuration来改变配置将不会发生作用。
使用编码配置可以通过Configuration对象的dynamicConfig()方法指定。
maxBytesLocalHeap(可选):An optional setting that constraints the memory usage of the Caches managed by the CacheManager to use at most the specified number of bytes of the local VM's heap.
maxBytesLocalOffHeap(可选):An optional setting that constraints the offHeap usage of the Caches managed by the CacheManager to use at most the specified number of bytes of the local VM's offHeap memory.
maxBytesLocalDisk(可选):An optional setting that constraints the disk usage of the Caches managed by the CacheManager to use at most the specified number of bytes of the local disk.
在CacheManager级别指定允许使用的磁盘最大容量。单位可以是K、M、G。
指定该属性后隐式的使所有Cache的overflowToDisk属性值变为true,
如需关闭则需在对应的Cache上设置overflowToDisk属性值为false。
-->
<!--
diskStore元素(net.sf.ehcache.config.DiskStoreConfiguration类):
Add a disk store to the cache manager, only one disk store can be added.
To turn off disk store path creation, comment out the diskStore element in ehcache.xml.
指定一个文件目录,当ehcache将数据写到磁盘上时存放在该文件目录下,可以使用JVM环境变量。
注释diskStore元素则会关闭磁盘缓存。
diskStore元素的属性:path
If it is not configured, and a cache is created which requires a disk store,
a warning will be issued and java.io.tmpdir will automatically be used.
如果没有设置path属性值,默认使用java.io.tmpdir目录。
user.home:用户的主目录。
user.dir:用户的当前工作目录,即当前程序对应的路径。
java.io.tmpdir:默认的temp文件目录。
其它通过命令行指定的系统属性,例如"java -Dehcache.disk.store.dir=D:/ehcache/diskdir"。
-->
<diskStore path="D:/ehcache/diskdir"/>
<!--
cacheManagerEventListenerFactory元素:
这个对象在添加和删除缓存对象的时候会得到相应的通知。
如果没有实现类被指定,则系统不创建CacheManager的监听器,没有默认值。
cacheManagerEventListenerFactory元素的属性:
class:CacheManagerEventListenerFactory的实现类。
properties:CacheManagerEventListenerFactory的属性值,以逗号","分隔多个属性。
propertySeparator:属性分隔符。
-->
<cacheManagerEventListenerFactory class="" properties=""/>
<!--
cacheManagerPeerProviderFactory元素:
在进行分布式缓存的应用时需要指定CacheManagerPeerProviderFactory,
用来生成CacheManagerPeerProvider的实例,以便和集群中的其他CacheManager通信。
CacheManagerPeerProviderFactory元素的属性:
class:CacheManagerPeerProviderFactory的实现类。
properties:CacheManagerPeerProviderFactory的属性值,以逗号","分隔多个属性。
Ehcache内建了2种基于RMI分布系统的通信策略:
automatic :使用多播组。在一个节点加入或者推出集群的时候自动感应。
manual :硬编码方式
propertySeparator:属性分隔符。
-->
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,"/>
<!--
cacheManagerPeerListenerFactory元素:
在进行分布式缓存的应用时需要指定CacheManagerPeerListenerFactory,
用来生成CacheManagerPeerListenerFactory的实例,以便和集群中的其他CacheManager通信。
cacheManagerPeerListenerFactory元素的属性:
class:CacheManagerPeerListenerFactory的实现类。
properties:CacheManagerPeerListenerFactory的属性值,以逗号","分隔多个属性。
propertySeparator:属性分隔符。
-->
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties=""/>
<!--
cache元素的属性(net.sf.ehcache.config.CacheConfiguration类):
diskExpiryThreadIntervalSeconds:Sets the interval in seconds between runs of the disk expiry thread.
设置检查磁盘缓存元素是否过期的线程运行的时间间隔,以秒为单位。默认为120秒。
diskSpoolBufferSizeMB:Sets the disk spool size, which is used to buffer writes to the DiskStore.
设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个cache都应有自己的一个缓存区。
diskPersistent(deprecated):Sets whether the disk store persists between CacheManager instances.
Note that this operates independently of overflowToDisk.
设置是否缓存虚拟机重启期数据。默认为false。
被cache元素的子元素persistence取代。
eternal:Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired.
False by default.
设置缓存对象是否会过期。如果为true表示缓存对象永不过期,设置后将忽略timeToIdleSeconds和timeToLiveSeconds属性。
默认为false。
maxElementsInMemory(deprecated):Sets the maximum objects to be held in memory (0 = no limit).
设置内存中最大缓存对象数,0表示不限制。被maxEntriesLocalHeap取代。
maxEntriesLocalHeap:Sets the maximum objects to be held in local heap memory (0 = no limit).
设置内存中存放元素的最大数量,0表示不限制。
memoryStoreEvictionPolicy:Sets the eviction policy. An invalid argument will set it to LRU.
设置当达到maxElementsInMemory限制时,ehcache将会根据指定的策略清理缓存。默认策略是LRU。
1.LRU:least recently used
LRU is the default setting.
The last-used timestamp is updated when an element is put into the cache or an element is retrieved from the cache with a get call.
最近最少被使用的。默认策略。
缓存元素有一个时间戳lastAccessTime属性,时间戳离当前时间最远的元素将会被清出缓存。
2.LFU:least frequently used
For each get call on the element the number of hits is updated.
When a put call is made for a new element (and assuming that the max limit is reached for the memory store) the element with least number of hits,
the Less Frequently Used element, is evicted.
一直以来最少被使用的。
缓存元素有一个hitCount属性,hitCount值最小的元素将会被清出缓存。
3.FIFO:first in first out, the oldest element by creation time
Elements are evicted in the same order as they come in.
When a put call is made for a new element (and assuming that the max limit is reached for the memory store) the element that was placed first (First-In) in the store is the candidate for eviction (First-Out).
先进先出。
除了lastAccessTime属性,缓存元素另外还有creationTime属性和lastUpdateTime属性,creationTime或lastUpdateTime值最小的元素将会被清出缓存。
4.CLOCK:first in first out, the oldest element by creation time
先进先出。
clearOnFlush:Sets whether the MemoryStore should be cleared when flush() is called on the cache - true by default.
设置在调用Cache的flush()方法时是否清空MemoryStore。默认为true。
name:Sets the name of the cache. This is used to identify the cache. It must be unique.
The following characters are illegal: ',', '=', ':', '"', '*' or '?'.
设置cache的唯一标识。
overflowToDisk(deprecated):Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit.
设置当内存缓存的对象数目达到maxElementsInMemory后,是否将溢出对象写到磁盘中。
如果overflowToDisk为false,maxElementsOnDisk(maxEntriesLocalDisk)属性将不会发生作用。
(注:写入到磁盘中的对象必须实现了Serializable接口。)
被cache元素的子元素persistence取代。<persistence strategy="localTempSwap"/>
timeToIdleSeconds:Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
The default amount of time to live for an element from its last accessed or modified date.
设置允许对象处于空闲状态的最长时间,以秒为单位。
当对象最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,
这个对象就会过期,ehcache将把它从缓存中清除。
当eternal属性值为false时该属性有效。
0表示对象可以无限期处于空闲状态。
timeToLiveSeconds:Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
The default amount of time to live for an element from its creation date.
设置允许对象存在于缓存中的最长时间,以秒为单位。
当对象被存放到缓存中后,如果处于缓存中的时间超过了timeToLiveSeconds属性值,
这个对象就会过期,ehcache将把它从缓存中清除。
当eternal属性值为false时该属性有效。
0表示对象可以无限期存在于缓存中。
timeToLiveSeconds属性值必须大于timeToIdleSeconds才有意义。
maxElementsOnDisk(deprecated):Sets the maximum number elements on Disk. 0 means unlimited.
设置磁盘中最大缓存对象数,0表示不限制。
被maxEntriesLocalDisk(unclustered caches)和maxEntriesInCache(clustered caches)取代。
maxEntriesLocalDisk:Sets the maximum number elements on Disk. 0 means unlimited.
设置磁盘中存放元素的最大数量,0表示不限制。
maxEntriesInCache:Sets the maximum number of entries in the cache.
Only applies to terracotta clustered caches.
设置缓存中存放元素的最大数量,只应用于Terracotta分布式缓存。
copyOnRead:Sets whether the Cache should copy elements it returns.
当设置该属性值为true时,从cache中读数据取到的是cache中对应元素的一个copy副本,而不是对应的一个引用。默认为false。
copyOnWrite:Sets whether the Cache should copy elements it gets.
当设置该属性为true时,往cache中写入数据用的是原对象的一个copy副本,而不是对应的一个引用。默认为false。
overflowToOffHeap:Enables or disables offheap store for the cache.
When an element is added to a cache and it goes beyond its maximum memory size,
an existing element is either deleted, if overflow is not enabled,
or evaluated for spooling to another tier, if overflow is enabled.
The overflow options are overflowToOffHeap and <persistence> (disk store).
设置当内存缓存的对象数目达到maxElementsInMemory后,是否将溢出对象写到非堆内存中。
(注:该属性只对企业版Ehcache有用。写入到磁盘中的对象必须实现了Serializable接口。)
maxBytesLocalHeap:
maxBytesLocalOffHeap:
maxBytesLocalDisk:
cache元素的子元素:
cacheEventListenerFactory:注册相应的的缓存监听类,用于处理缓存事件,如put、remove、update和expire。
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties=
"replicateAsynchronously=true,//whether replications are asyncrhonous (true) or synchronous (false). Defaults to true.复制操作是异步还是同步。
replicatePuts=true,//whether new elements placed in a cache are replicated to others. Defaults to true.当新对象被放入缓存,集群内其它缓存是否也放入
replicateUpdates=true,//whether new elements which override an element already existing with the same key are replicated. Defaults to true.当新对象覆盖原有相同key的对象,集群内其它缓存是否也复制操作
replicateUpdatesViaCopy=false,//whether the new elements are copied to other caches (true), or whether a remove message is sent. Defaults to true
replicateRemovals=true"/>//whether element removals are replicated. Defaults to true.对象被移除,是否复制状态到集群中其它缓存
bootstrapCacheLoaderFactory:指定相应的BootstrapCacheLoader,用于初始化缓存,以及自动设置。
pinning:表示将缓存内的元素固定住,除非过期,否则不会对它进行删除和驱除到其他储存容器中。
pinning元素只定义了一个属性store,表示将元素固定在什么位置。
localMemory:将元素固定在内存中。
inCache:将元素固定在任何其正在保存的容器中。
copyStrategy(net.sf.ehcache.config.CopyStrategyConfiguration类):
当指定copyOnRead或者copyOnWrite为true时,启用拷贝策略。
默认的copyStrategy是通过序列化实现,可以实现net.sf.ehcache.store.compound.CopyStrategy接口来实现自定义的CopyStrategy,
需要在cache元素下定义一个copyStrategy元素并指定其class属性值为自定义的CopyStrategy实现类。
例如<copyStrategy class="xxx.xxx.xxx"/>。
persistence:表示cache的持久化,属性strategy表示当前cache对应的持久化策略。
localTempSwap:当堆内存或者非堆内存中的元素已满时,将溢出的元素写到磁盘上,一旦重启就会消失。
localRestartable:该策略只对企业级ehcache产生作用。它可以在重启的时候将堆内存或者非堆内存中的元素持久化到磁盘上,重启之后从磁盘上恢复元素到内存中。
none:不持久化缓存的元素。
distributed:应用于分布式缓存。
-->
<!-- 设置默认缓存策略,必需元素,缺省则抛出org.hibernate.cache.CacheException: net.sf.ehcache.CacheException: Caches cannot be added by name when default cache config is not specified in the config. -->
<defaultCache
maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="300"
overflowToDisk="true">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!--
Hibernate提供了三种和查询相关的缓存区域:
默认的查询缓存区域:org.hibernate.cache.StandardQueryCache
时间戳缓存区域:org.hibernate.cache.UpdateTimestampCache
用户自定义的查询缓存区域
默认的查询缓存区域以及用户自定义的查询缓存区域都用于存放查询结果。
时间戳缓存区域用于存放对与查询结果相关的表进行插入、更新或删除操作的时间戳。
Hibernate通过时间戳缓存区域来判断被缓存的查询结果是否过期,当应用程序对数据库的相关数据做了修改,Hibernate会自动刷新缓存的查询结果。
如果其他应用程序对数据库的相关数据做了修改,则无法监测,此时必须由应用程序调用Query接口的setForceCacheRefresh(true)方法手动刷新查询结果。
-->
<!--
设置默认查询缓存策略
(注:在查询缓存中并不缓存结果集中所包含实体的所有字段,只缓存这些实体的标识符属性的值、以及标识符值的类型。)
-->
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxEntriesLocalHeap="500"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--
设置时间戳缓存策略
当通过hibernate更新数据的时候,hibernate会更新操作表的最后更新时间。
每个查询缓存都有一个生成时间和这个缓存所查询的表。
当hibernate查询一个缓存是否存在的时候,如果缓存存在,则取出缓存的生成时间和这个缓存所查询的表,
然后去查找这些表的最后更新时间,如果这张表在生成时间后更新过了,那么该缓存失效。
-->
<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxEntriesLocalHeap="500"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 设置用户自定义缓存策略 -->
<cache name="xxx.xxx.xxx.Order"
maxEntriesLocalHeap="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- 设置用户自定义缓存策略 -->
<cache name="xxx.xxx.xxx.Order.items"
maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LFU"
overflowToDisk="true"
/>
</ehcache>