参考博文1:ehcache 集群使用 rmi方式 有图有真想
参考博文2:EhCache 分布式缓存/缓存集群
讲一下背景,两台服务器,pc跟移动端,一个数据库,在pc服务器上,用了Hibernate的二级缓存,但是最近老是报错,pc端删除了数据,移动端没有及时更新缓存,导致报
nested exception is org.hibernate.ObjectNotFoundException:No row with the given identifier exists:
一开始报这个错,网上说是懒加载问题,关联数据被删了之类的,然而我看了一下并不是。就跟师兄讨论,他说要用分布式缓存策略来解决,我就上网查了下,第一次用,中间出现各种没遇到的问题。然后我根据开头给的两个博客结合起来改配置文件。详情请点击查看
根据第二个篇文配置,cacheEventListenerFactory会报错,
RMI net.sf.ehcache.CacheException: Unable to load class net.sf.ehcache.boots...
先看配置文件,是在ehcache.xml里面配的:
在原来的ehcache.xml础上加入
<!--
集群多台服务器中的缓存,这里是要同步一些服务器的缓存
server1(PC) hostName:xxx.xxx.xxx.xxx pc的ip地址 port:40001 UpdateTimestampsCache
server2(移动) hostName:<span style="font-family: Arial, Helvetica, sans-serif;">xxx.xxx.xxx.xxx 移动端的ip地址</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span>port:40002 UpdateTimestampsCache
注意:每台要同步缓存的服务器的RMI通信socket端口都不一样,在配置的时候注意设置
-->
<!-- PC 的cacheManagerPeerProviderFactory配置 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="
port=40001,
socketTimeoutMillis=2000,
peerDiscovery=manual,
rmiUrls=//xxx.xxx.xxx.xxx(移动服务器ip):40002/org.hibernate.cache.spi.UpdateTimestampsCache"
propertySeparator=","
/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40001, socketTimeoutMillis=2000"
/>
<!--
name:cache唯一标识
eternal:缓存是否永久有效
maxElementsInMemory:内存中最大缓存对象数
overflowToDisk(true,false):缓存对象达到最大数后,将缓存写到硬盘中
diskPersistent:硬盘持久化
timeToIdleSeconds:缓存清除时间
timeToLiveSeconds:缓存存活时间
memoryStoreEvictionPolicy:缓存清空策略
1.FIFO:first in first out 先讲先出
2.LFU: Less Frequently Used 一直以来最少被使用的
3.LRU:Least Recently Used 最近最少使用的
-->
<!--
RMI缓存分布同步查找 class使用net.sf.ehcache.distribution.RMICacheReplicatorFactory
这个工厂支持以下属性:
replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers。默认是true。
replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制。默认是true。
replicateRemovals= true | false – 当元素移除的时候是否进行复制。默认是true。
replicateAsynchronously=true | false – 复制方式是异步的指定为true时,还是同步的,指定为false时。默认是true。
replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制指定为true时为复制,默认是true。
replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制指定为true时为复制,默认是true。
asynchronousReplicationIntervalMillis=1000
-->
<!-- 监听RMI同步缓存对象配置 注册相应的的缓存监听类,用于处理缓存事件,如put,remove,update,和expire -->
<!-- 设置默认的查询缓存的数据过期策略 -->
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="5000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="7200"
overflowToDisk="true">
</cache>
<!-- 设置时间戳缓存的数据过期策略 -->
<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
/>
<!-- 用于在初始化缓存,以及自动设置 -->
<bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>
解释一下为什么是
rmiUrls=//xxx.xxx.xxx.xxx(移动服务器ip):40002/org.hibernate.cache.spi.UpdateTimestampsCache
因为查询缓存的话会抛异常:对象没有序列号异常,但是不影响程序运行,影响缓存。
因为我这边是改动数据没有及时更新缓存,所以只配了
UpdateTimestampsCache,根据需求改。
另一个服务器移动端的:
其他配置一样,只是改动
<!-- server2 的cacheManagerPeerProviderFactory配置 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="
<span style="white-space:pre"> </span>port=40002,
socketTimeoutMillis=2000,
peerDiscovery=manual,
rmiUrls=//xxx.xxx.xxx.xxx(PC的ip):40001/org.hibernate.cache.spi.UpdateTimestampsCache"
/>
接着尝试把它配进Hibernate里面,再把原来自己的缓存给分开,一个session-ehcache.xml(放自己的缓存配置)跟原来的ehcache.xml。然后在spring的Hibernate sessionFactory里面配:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean>
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>...
<pre name="code" class="java"><prop key="hibernate.cache.provider_configuration_file_resource_path">classpath:ehcache.xml</prop>
...
再把自己的加进去:
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:session_ehcache.xml"/>
</bean>
转载无需注明出处------------------------guin_guo