您基本上有 2 个问题 - 首先,当非连贯缓存启动时其他正在运行的缓存变为空,并且 其次 新启动的非连贯缓存不同步自动与其他正在运行的缓存。让我尝试一一解决。
当非连贯缓存启动时,其他正在运行的缓存变为空
Ehcache 有几个属性定义了缓存之间的同步将如何发生,这些属性定义了缓存是否应该通过复制或失效来复制到其他缓存。请参阅this。因此,基本上您需要将 Ehcache 配置为“通过复制复制”而不是“通过无效复制”。一旦你处理了这件事,你的第一个问题就会得到解决。
为了方便参考,我将您应该使用的值放入(我在我的应用程序中使用相同的配置):
########## EhCache related properties ##########
peerDiscoveryMechanism=manual
replicatePuts=true
replicatePutsViaCopy=true
replicateUpdates=true
replicateUpdatesViaCopy=true
replicateRemovals=true
replicateAsynchronously=false
现在,您可以通过多种方式进行设置,我可以告诉您我是如何做到的。我已将它们放在一个属性文件中并加载它并在我的应用程序中使用。基本上你需要在 Echache 的RMICacheReplicatorFactory 中配置这些并将其用作你的缓存cacheEventListenerFactory。所以,我在 ehcache.xml 中定义了以下配置
<cache name="itdTestResultsCache" maxElementsInMemory="100000" eternal="true" overflowToDisk="false">
<cacheEventListenerFactory class="com.cgi.itd.customComponents.serverCache.ItdRMICacheReplicatorFactory" />
</cache>
然后我的自定义ItdRMICacheReplicatorFactory 类如下。请注意,它有代码来加载属性然后使用它 - String replicatePutsString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_PUTS);,我不会给你那段代码,你可以硬编码或自己写。
import java.util.Properties;
import net.sf.ehcache.distribution.RMICacheReplicatorFactory;
import net.sf.ehcache.util.PropertyUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.cgi.itd.customComponents.ITDPropertyPlaceholderConfigurer;
import com.cgi.itd.utils.ITDApplicationConstants;
/**
* Custom handler for RMI replicator factory
* @author himanshu.agrawal
*
*/
public class ItdRMICacheReplicatorFactory extends RMICacheReplicatorFactory {
Log log = LogFactory.getLog(ItdRMICacheReplicatorFactory.class);
public ItdRMICacheReplicatorFactory() {
log.info("ItdRMICacheReplicatorFactory constructor.");
}
/**
* Extracts the value of asynchronousReplicationIntervalMillis. Sets it to 1000ms if
* either not set or there is a problem parsing the number
* @param properties
*/
@Override
protected int extractReplicationIntervalMilis(Properties properties) {
int asynchronousReplicationIntervalMillis;
String asynchronousReplicationIntervalMillisString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS);
if (asynchronousReplicationIntervalMillisString != null) {
try {
int asynchronousReplicationIntervalMillisCandidate =
Integer.parseInt(asynchronousReplicationIntervalMillisString);
if (asynchronousReplicationIntervalMillisCandidate < ITDApplicationConstants.MINIMUM_REASONABLE_INTERVAL) {
log.debug("Trying to set the asynchronousReplicationIntervalMillis to an unreasonable number." +
" Using the default instead.");
asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
} else {
asynchronousReplicationIntervalMillis = asynchronousReplicationIntervalMillisCandidate;
}
} catch (NumberFormatException e) {
log.warn("Number format exception trying to set asynchronousReplicationIntervalMillis. " +
"Using the default instead. String value was: '" + asynchronousReplicationIntervalMillisString + "'");
asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
}
} else {
asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
}
log.debug("Extracted asynchronousReplicationIntervalMillis = " + asynchronousReplicationIntervalMillis);
return asynchronousReplicationIntervalMillis;
}
/**
* Extracts the value of replicateAsynchronously from the properties
* @param properties
*/
@Override
protected boolean extractReplicateAsynchronously(Properties properties) {
boolean replicateAsynchronously;
String replicateAsynchronouslyString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_ASYNCHRONOUSLY);
if (replicateAsynchronouslyString != null) {
replicateAsynchronously = PropertyUtil.parseBoolean(replicateAsynchronouslyString);
} else {
replicateAsynchronously = true;
}
log.debug("Extracted replicateAsynchronously = " + replicateAsynchronously);
return replicateAsynchronously;
}
/**
* Extracts the value of replicateRemovals from the properties
* @param properties
*/
@Override
protected boolean extractReplicateRemovals(Properties properties) {
boolean replicateRemovals;
String replicateRemovalsString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_REMOVALS);
if (replicateRemovalsString != null) {
replicateRemovals = PropertyUtil.parseBoolean(replicateRemovalsString);
} else {
replicateRemovals = true;
}
log.debug("Extracted replicateRemovals = " + replicateRemovals);
return replicateRemovals;
}
/**
* Extracts the value of replicateUpdatesViaCopy from the properties
* @param properties
*/
@Override
protected boolean extractReplicateUpdatesViaCopy(Properties properties) {
boolean replicateUpdatesViaCopy;
String replicateUpdatesViaCopyString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_UPDATES_VIA_COPY);
if (replicateUpdatesViaCopyString != null) {
replicateUpdatesViaCopy = PropertyUtil.parseBoolean(replicateUpdatesViaCopyString);
} else {
replicateUpdatesViaCopy = true;
}
log.debug("Extracted replicateUpdatesViaCopy = " + replicateUpdatesViaCopy);
return replicateUpdatesViaCopy;
}
/**
* Extracts the value of replicatePutsViaCopy from the properties
* @param properties
*/
@Override
protected boolean extractReplicatePutsViaCopy(Properties properties) {
boolean replicatePutsViaCopy;
String replicatePutsViaCopyString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_PUTS_VIA_COPY);
if (replicatePutsViaCopyString != null) {
replicatePutsViaCopy = PropertyUtil.parseBoolean(replicatePutsViaCopyString);
} else {
replicatePutsViaCopy = true;
}
log.debug("Extracted replicatePutsViaCopy = " + replicatePutsViaCopy);
return replicatePutsViaCopy;
}
/**
* Extracts the value of replicateUpdates from the properties
* @param properties
*/
@Override
protected boolean extractReplicateUpdates(Properties properties) {
boolean replicateUpdates;
String replicateUpdatesString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_UPDATES);
if (replicateUpdatesString != null) {
replicateUpdates = PropertyUtil.parseBoolean(replicateUpdatesString);
} else {
replicateUpdates = true;
}
log.debug("Extracted replicateUpdates = " + replicateUpdates);
return replicateUpdates;
}
/**
* Extracts the value of replicatePuts from the properties
* @param properties
*/
@Override
protected boolean extractReplicatePuts(Properties properties) {
boolean replicatePuts;
String replicatePutsString = ITDPropertyPlaceholderConfigurer.getPropertiesMap().get(ITDApplicationConstants.REPLICATE_PUTS);
if (replicatePutsString != null) {
replicatePuts = PropertyUtil.parseBoolean(replicatePutsString);
} else {
replicatePuts = true;
}
log.debug("Extracted replicatePuts = " + replicatePuts);
return replicatePuts;
}
}
所以这将解决您的第一个问题,即当出现不连贯的缓存时,它会删除正在运行的缓存中的所有条目。现在,进入第二个。
新启动的非一致缓存不会自动与其他正在运行的缓存同步
请参阅this 答案,它会告诉您如何自动执行此操作,否则您也可以通过一段代码手动执行此操作,以使用值加载新启动的非连贯缓存。
提示如果您不知道如何手动操作 - 当您的应用程序启动时加载数据(从 DB 或平面文件等),然后使用 cache.put 放置它进入缓存。