目录
3.2.1 配置PeerProvider,使用tcp的方式 9
3.2.2 为每个Cache添加cacheEventListener 9
1 前言
1.1 背景
系统缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能. 缓存设想内存是有限的,缓存的时效性也是有限的,所以可以设定内存数量的大小,可以执行失效算法 ,可以在内存满了的时候,按照最少访问等算法将缓存直接移除或切换到硬盘上。
Ehcache从 Hibernate发展而来,逐渐涵盖了Cahce界的全部功能,是目前发展势头最好的一个项目。具有快速,简单,低消耗,依赖性小,扩展性强,支持对象或序列化缓存,支持缓存或元素的失效,提供LRU、LFU和FIFO缓存策略,支持内存缓存和磁盘缓存,分布式缓存机制等等特点。
Cache 存储方式 :内存或磁盘。
官方网站:http://ehcache.sourceforge.net/
1.2 主要特性
1. 快速.
2. 简单.
3. 多种缓存策略
4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
5. 缓存数据会在虚拟机重启的过程中写入磁盘
6. 可以通过RMI、可插入API等方式进行分布式缓存
7. 具有缓存和缓存管理器的侦听接口
8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
9. 提供Hibernate的缓存实现
1.3 使用注意点
当用Hibernate的方式修改表数据(save,update,delete等等),这时EhCache会自动把缓存中关于此表的所有缓存全部删除掉(这样能达到同步)。但对于数据经常修改的表来说,可能就失去缓存的意义了(不能减轻数据库压力);
1.4 使用场合
比较少更新表数据
EhCache一般要使用在比较少执行write操作的表(包括update,insert,delete等)[Hibernate的二级缓存也都是这样];
对并发要求不是很严格的情况
两台机子中的缓存是不能实时同步的;
1.5 参考文献
ITeye论坛
http://scholers.iteye.com/category/127647?show_full=true
http://wozailongyou.iteye.com/blog/230252
2 基本配置
2.1 ehcache.XML
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="Java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000" <!- 缓存最大数目 ->
eternal="false" <!- 缓存是否持久 ->
overflowToDisk="true" <!- 是否保存到磁盘,当系统当机时->
timeToIdleSeconds="300" <!- 当缓存闲置n秒后销毁 ->
timeToLiveSeconds="180" <!- 当缓存存活n秒后销毁->
diskPersistent="false"
diskExpiryThreadIntervalSeconds= "120"/>
</ehcache>
2.2 参数详解
eternal(必填项):如果为true,则永不过期,忽略后两个参数的设置。
timeToIdleSeconds: 空闲无访问时间,默认为0,永不过时。
timeToLiveSeconds: 空闲无访问时间,默认为0,永不过时。
移出算法:如果经过失效算法后,还是有很多有效的缓存,则执行清除算法。清除算法由两个参数组成:
memoryStoreEvictionPolicy: 默认为LRU(最近最少访问),另有先进先出(FIFO),最少访问次数(LFU)
overflowToDisk(必填项):为true,则将清除出来的缓存持久化到磁盘,否则销毁。
maxElementsOnDisk:默认为0,无限多。存储到硬盘
diskExpiryThreadIntervalSeconds:使用过期算法清除磁盘中失效对象的间隔,默认为120秒。
diskSpoolBufferSizeMB :默认为30M。
diskPersistent :当应用重启时,可将缓存先持久化到硬盘,重启后再行载入,节省大量的重新从数据库载入。但只适合那些缓存不怎么变化,或者有特殊机制保证重启后应用能接收到重启这段时间里缓存变化信息的情况。
ehcache中缓存的3种清空策略:
FIFO(first in first out):先进先出
LFU( Less Frequently Used):一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU(Least Recently Used):最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
2.3 hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.show_sql">true</property>
<!-- 指定cache实现类 -->
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 启用二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 启用查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!--<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache2.xml</property>//指定ehcache配置文件 -->
<mapping class="test.po.TUser" />
</session-factory>
</hibernate-configuration>
2.4 配置相关实体的缓存策略
@Entity
@Table(name="cui_user")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)//可读可写
public class TUser {
private Integer id;
private String name;
@Id //标识主键
@GeneratedValue(strategy=GenerationType.AUTO)//指定主键值的产生策略由Hibernate根据数据库字段选择
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3 分布式缓存
3.1 RMI方式
假设你在集群中有两台服务器。你要同步 sampleCache1 和 sampleCache2。下面是每个
服务器需要的配置:
3.1.1 设置自身
Server1
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=Server1, port=40001,socketTimeoutMillis=2000" />
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual,
rmiUrls=//server2:40001/sampleCache1|//server2:40001/sampleCache2"/>
3.1.2 设置需要同步的对方服务器及缓存
Server2
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=Server2, port=40001,socketTimeoutMillis=2000" />
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40001/sampleCache1|//server1:40001/sampleCache2"/>
如果还有第三台机器,则继续用|分割,继续往下列。
3.1.5 缓存对象的配置
往每一个需要缓存的对象加入子对象cacheEventListenerFactory
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,
replicatePuts=true,
replicateUpdates=true,
replicateUpdatesViaCopy=true,
replicateRemovals=true
asynchronousReplicationIntervalMillis=<number of milliseconds">
propertySeparator="," />
replicateAsynchronously 对象同步是否异步完成,默认为true。如果比较紧急就设为false。 在一致性时间性要求不强的时候,设为异步可大大提供性能,因为它是异步立即返回的,而且可以批量提交。
replicateUpdatesViaCopy 是否将对象变更复制到所有节点,还是只是发送一个失效信息,让对方该缓存失效,当对方需要该缓存时重新计算载入。
默认为true。鉴于对象复制的消耗挺大的,又有锁的问题,而且对方也未必需要该对象,所以此属性建议设为false。如果业务上真的需要设为true时,就可考虑使用Terracotta了。
replicatePuts、replicateUpdates、replicateRemovals 增删改是否同步,默认都为true。但因为我们前面选择了失效算法,所以replicatePuts 要设为false。
一般情况下的配置为:
<cache name="org.springside.examples.miniweb.entity.user.User" maxElementsInMemory="500" overflowToDisk="true"
eternal="true">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=false,replicatePuts=false,replicateUpdatesViaCopy=false" />
</cache>
3.1.6 完整的配置文件(server1)
1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
2. <cacheManagerPeerProviderFactory class=
3. "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
4. properties="peerDiscovery=manual,
5. rmiUrls=//10.129.0.203:40000/sampleCache1¦//10.129.0.203:40000/ sampleCache2"/>
6.
7. <cacheManagerPeerListenerFactory
8. class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
9. properties="hostName=10.129.0.202,port=40000, socketTimeoutMillis=120000"/>
10.
11. <defaultCache
12. maxElementsInMemory="10000"
13. eternal="false"
14. timeToIdleSeconds="120"
15. timeToLiveSeconds="120"
16. overflowToDisk="true"
17. diskSpoolBufferSizeMB="30"
18. maxElementsOnDisk="10000000"
19. diskPersistent="false"
20. diskExpiryThreadIntervalSeconds="120"
21. memoryStoreEvictionPolicy="LRU"
22. <cacheEventListenerFactory
23. class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
24. />
25.
26. <cache name="sampleCache1"
27. maxElementsInMemory="1000"
28. eternal="false"
29. timeToIdleSeconds="100000"
30. timeToLiveSeconds="100000"
31. overflowToDisk="false">
32. <cacheEventListenerFactory
33. class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
34. </cache>
3.1.7 集群的作用
集群主要有两个方面的作用 1、负载分流。2、安全
如果一个web应用的访问量不是很多的话,集群和非集群的效果相差不了多少,甚至有的时候集群会消耗更多的资源,导致垃圾回收频繁,内存占用率高等的现象。当然,如果访问量大,那当然是集群的效果会好很多。
那在访问量小的时候是不是就不用做集群呢,答案是否定的。集群的另外一个好处就是数据和状态的安全性,EHCache会自动同步集群中服务器的缓存,当一 台服务器挂掉后,另外的服务器可以马上接上来,防止用户状态数据丢失,所以,对安全性的保障是十分有效的。
3.2 JGroups方式
3.2.1 配置PeerProvider,使用tcp的方式
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
properties="connect=TCP(start_port=7800):
TCPPING(initial_hosts=192.168.2.22[7800],192.168.2.21[7800];port_range=10;timeout=3000;
num_initial_members=3;up_thread=true;down_thread=true):
VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):
pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_timeout=3000):
pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;
print_local_addr=false;down_thread=true;up_thread=true)"
propertySeparator="::" />
JGroup方式配置的两个server上的配置文件一样,若有多个server,在initial_hosts中将server ip加上即可
3.2.3 为每个Cache添加cacheEventListener
<cache name="userCache" maxElementsInMemory="10000" eternal="true"
overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>
3.2.4 完整的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.sf.net/ehcache.xsd">
<diskStore path="java.io.tmpdir" />
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
properties="connect=TCP(start_port=7800):
TCPPING(initial_hosts=192.168.2.154[7800],192.168.2.23[7800];port_range=10;timeout=3000;
num_initial_members=3;up_thread=true;down_thread=true):
VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):
pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_timeout=3000):
pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;
print_local_addr=false;down_thread=true;up_thread=true)"
propertySeparator="::" />
<defaultCache maxElementsInMemory="10000" eternal="true"
overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</defaultCache>
<cache name="velcroCache" maxElementsInMemory="10000" eternal="true"
overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>
<cache name="userCache" maxElementsInMemory="10000" eternal="true"
overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>
<cache name="resourceCache" maxElementsInMemory="10000"
eternal="true" overflowToDisk="true" timeToIdleSeconds="0"
timeToLiveSeconds="0" diskPersistent="false"
diskExpiryThreadIntervalSeconds="120">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>
</ehcache>
3.3 JMS方式
具体详情请参照http://www.ehcache.org/documentation/user-guide/jms-replicated-caching