【发布时间】:2014-10-10 15:26:49
【问题描述】:
为什么 ehcache 不传播过期事件?你是怎么处理的?
这是我的情况。我有两个使用 RMI 相互同步的节点。我的配置如下:
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual, rmiUrls=//localhost:51001/sessionCache|//localhost:51002/sessionCache"/>
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=0.0.0.0, port=51002, socketTimeoutMillis=2000"/>
<diskStore path="java.io.tmpdir"/>
<cache name="sessionCache"
maxEntriesLocalHeap="20000"
maxEntriesLocalDisk="100000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="60"
memoryStoreEvictionPolicy="LRU"
transactionalMode="off">
<persistence strategy="localTempSwap"/>
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties="replicateAsynchronously=true" />
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=false"
propertySeparator=","/>
</cache>
现在想象以下场景:
- 对服务器 A 的登录调用创建了会话,该会话被放入复制缓存中。
- 连续调用服务器 A 以从缓存中获取会话对象将为其重置
timeToIdleSeconds计数器。 - 继续调用服务器 A 65 秒以确保服务器 B 上的会话将过期,在步骤 1 中将会话对象放入缓存后从未调用过该会话。
- 调用服务器 B。在内部,它将从本地缓存中删除会话对象,并调用
RegisteredEventListeners.internalNotifyElementExpiry,最终调用RMISynchronousCacheReplicator.notifyElementExpired。
在第 4 步中,我希望服务器 B 将 RmiEventType.REMOVE 发送到服务器 A。而 RMISynchronousCacheReplicator.notifyElementExpired 具有以下正文
public final void notifyElementExpired(final Ehcache cache, final Element element) {
/*do not propagate expiries. The element should expire in the remote cache at the same time, thus
preseerving coherency.
*/
}
看起来RMICacheReplicatorFactory 的创建者从未考虑过timeToIdleSeconds 驱逐算法。
在每个 cache.get() 之后手动调用 cache.replace() 是否是重置集群中 TTI (timeToIdle) 的唯一方法?
在notifyElementExpired 中调用cache.remove() 的附加cacheEventListener 是从集群中删除过期元素的唯一方法吗?
【问题讨论】: