ehcache keySet使用getKeysWithExpiryCheck()方法时超时



我使用ehcache来控制用户会话,每隔一段时间我在用户登录时看到日志中的这个错误。

net.sf.ehcache.constructs.nonstop.NonStopCacheException: keySet timed out
    at net.sf.ehcache.constructs.nonstop.concurrency.NonStopCacheKeySet$NonStopCacheKeySetIterator$1.performClusterOperationTimedOut(NonStopCacheKeySet.java:103)
    at net.sf.ehcache.constructs.nonstop.concurrency.NonStopCacheKeySet$NonStopCacheKeySetIterator$1.performClusterOperationTimedOut(NonStopCacheKeySet.java:96)
    at net.sf.ehcache.constructs.nonstop.store.ExecutorServiceStore.executeClusterOperation(ExecutorServiceStore.java:1187)
    at net.sf.ehcache.constructs.nonstop.store.NonstopStoreImpl.executeClusterOperation(NonstopStoreImpl.java:704)
    at net.sf.ehcache.constructs.nonstop.concurrency.NonStopCacheKeySet$NonStopCacheKeySetIterator.<init>(NonStopCacheKeySet.java:96)
    at net.sf.ehcache.constructs.nonstop.concurrency.NonStopCacheKeySet.iterator(NonStopCacheKeySet.java:56)
    at net.sf.ehcache.Cache.getKeysWithExpiryCheck(v.java:1906)
...

官方ehcache文档说:"考虑您的使用是否需要检查过期密钥。因为这个方法需要很长时间,取决于缓存设置,…"。

所以我不确定ecache.xml中的超时应该增加多少来阻止这个错误,尽管20000 ms对我来说似乎已经足够了,因为文档还提到每1000个条目所花费的时间大约是200ms。

这是使用的ehcache.xml。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="RelianceCache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">

    <cache name="READ_USERS_CACHE" maxElementsInMemory="0" eternal="true" overflowToDisk="false">
        <terracotta clustered="true" valueMode="serialization"  consistency="strong">
            <nonstop immediateTimeout="false" timeoutMillis="20000">
                <timeoutBehavior type="exception" />
            </nonstop>
        </terracotta>
    </cache>

    <terracottaConfig url="TSA_SERVERS:TSA_PORT" rejoin="true" />
</ehcache>

编辑:查看NonStopCacheKeySet实现,错误正在方法NonStopCacheKeySetIterator中抛出。

增加超时时间并不能解决问题。100个条目20秒的时间太长了。

如果从应用程序逻辑的角度来看是合适的,我会考虑将timeoutBehavior更改为timeoutBehavior="localReadsAndExceptionOnWrite"。请注意,localCacheEnabled属性必须为TRUE,这是默认值。

   ...
   <terracotta clustered="true" localCacheEnabled="true" valueMode="serialization"  consistency="strong">
        <nonstop immediateTimeout="false" timeoutMillis="20000">
            <timeoutBehavior type="localReadsAndExceptionOnWrite" />
        </nonstop>
    </terracotta>
    ...

另一个解决方案是将一致性更改为默认值consistency ="eventual"。这很可能会解决问题,但可能会导致缓存返回的数据暂时过期。


正如文档所述"考虑您的使用是否需要检查过期密钥…"。是否有可能调整应用程序逻辑以使用Cache.getKey()而不是遍历键列表?

最新更新