Java 我应该怎么做才能从集群缓存对等点引导缓存?
有三台服务器,它们都部署了ehcache。一台服务器由于某些原因关闭正常或异常,当我重新启动它时,我发现缓存变空,数据丢失了。当我检查其他两台服务器时,它们的缓存也变空了,数据也丢失了。我在ehcach.org/community/上问了这个问题,但没有回答。我在ehcache.org()中搜索了好几天,但我仍然不知道为什么。我刚找到下面的单词,但它并没有告诉我怎么做,所以我仍然无法避免上述情况 当一个对等点出现时,它将与其他缓存不一致。当引导程序完成时,它将 部分连贯。Bootstrap从随机对等方获取密钥列表,然后批量加载这些密钥 来自随机的同龄人。如果引导失败,那么缓存将不会启动(现在不是这样)。但是如果 发生分布式缓存操作,该操作随后被引导覆盖。缓存有可能 可能不一致 下面是我的ehcache.xmlJava 我应该怎么做才能从集群缓存对等点引导缓存?,java,caching,ehcache,Java,Caching,Ehcache,有三台服务器,它们都部署了ehcache。一台服务器由于某些原因关闭正常或异常,当我重新启动它时,我发现缓存变空,数据丢失了。当我检查其他两台服务器时,它们的缓存也变空了,数据也丢失了。我在ehcach.org/community/上问了这个问题,但没有回答。我在ehcache.org()中搜索了好几天,但我仍然不知道为什么。我刚找到下面的单词,但它并没有告诉我怎么做,所以我仍然无法避免上述情况 当一个对等点出现时,它将与其他缓存不一致。当引导程序完成时,它将 部分连贯。Bootstrap从随机
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false">
<diskStore path="java.io.tmpdir"/>
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="hostName=192.168.4.245, port=7800, socketTimeoutMillis=120000"/>
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual, rmiUrls=//192.168.4.250:7800/configInfoCache"/>
<defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0" diskPersistent="false" diskExpiryThreadIntervalSeconds="120"> </defaultCache>
<cache name="configInfoCache" maxElementsInMemory="10000" eternal="true" overflowToDisk="false" timeToIdleSeconds="0" timeToLiveSeconds="0" memoryStoreEvictionPolicy="LFU">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
<bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>
</ehcache>
ehcahe版本1.6.2
jdk版本1.6
tomcat 6.0.44
希望有人能告诉我怎么做,在ehcache.xml中配置或实现
一些接口。我在这个问题上花了很多时间。请!!!帮帮我
ps:这是我第一次问有关stackoverflow的问题,如果需要什么,请告诉我。你基本上有两个问题-首先,当非一致性缓存启动时,其他正在运行的缓存变为空,其次,新启动的非一致性缓存不会自动与其他正在运行的缓存同步。让我一个接一个地谈谈 当非一致缓存启动时,其他正在运行的缓存将变为空 Ehcache有两个属性,它们定义了缓存之间如何进行同步,这些属性定义了缓存是应该通过复制还是通过失效复制到其他缓存。参考因此,基本上您需要将Ehcache配置为“按副本复制”,而不是“按无效复制”。一旦你解决了这个问题,你的第一个问题就会得到解决 为了便于参考,我将列出您应该使用的值(我在应用程序中使用相同的配置): 现在,你可以用多种方式来设定,我可以告诉你我是如何做到的。我已经将它们放在属性文件中,并将其加载并在应用程序中使用。基本上,您需要在Ecache的
RMICacheReplicatorFactory
中配置它们,并将其用作缓存的cacheEventListenerFactory
。因此,我在我的ehcache.xml
<cache name="itdTestResultsCache" maxElementsInMemory="100000" eternal="true" overflowToDisk="false">
<cacheEventListenerFactory class="com.cgi.itd.customComponents.serverCache.ItdRMICacheReplicatorFactory" />
</cache>
因此,这将解决您的第一个问题,即当出现非一致缓存时,它将删除正在运行的缓存中的所有条目。现在来看第二个
新启动的非一致缓存不会自动与其他正在运行的缓存同步
请参考答案,它告诉您如何自动执行此操作,否则您也可以手动执行此操作,方法是使用一段代码加载新启动的具有值的非一致性缓存
提示如果您不知道如何手动操作-当应用程序启动时,请加载数据(从DB或平面文件等),然后使用
缓存。将放入缓存。您基本上有两个问题-首先,当非一致性缓存启动时,其他正在运行的缓存变为空,其次,新启动的非一致性缓存不会自动与其他正在运行的缓存同步。让我一个接一个地谈谈
当非一致缓存启动时,其他正在运行的缓存将变为空
Ehcache有两个属性,它们定义了缓存之间如何进行同步,这些属性定义了缓存是应该通过复制还是通过失效复制到其他缓存。参考因此,基本上您需要将Ehcache配置为“按副本复制”,而不是“按无效复制”。一旦你解决了这个问题,你的第一个问题就会得到解决
为了便于参考,我将列出您应该使用的值(我在应用程序中使用相同的配置):
现在,你可以用多种方式来设定,我可以告诉你我是如何做到的。我已经将它们放在属性文件中,并将其加载并在应用程序中使用。基本上,您需要在Ecache的RMICacheReplicatorFactory
中配置它们,并将其用作缓存的cacheEventListenerFactory
。因此,我在我的ehcache.xml
<cache name="itdTestResultsCache" maxElementsInMemory="100000" eternal="true" overflowToDisk="false">
<cacheEventListenerFactory class="com.cgi.itd.customComponents.serverCache.ItdRMICacheReplicatorFactory" />
</cache>
因此,这将解决您的第一个问题,即当出现非一致缓存时,它将删除正在运行的缓存中的所有条目。现在来看第二个
新启动的非一致缓存不会自动与其他正在运行的缓存同步
请参考答案,它告诉您如何自动执行此操作,否则您也可以手动执行此操作,方法是使用一段代码加载新启动的具有值的非一致性缓存
提示如果您不知道如何手动操作,请在应用程序启动时加载数据(从DB或平面文件等),然后使用缓存。将
放入缓存。谢谢!!第二个解决方案很有用!!事实上,您提到的第一个问题,ehcache有默认值,通过copy放置和更新,即使您没有设置,它也会像您所说的那样工作。很高兴知道您现在很好。您是否双重确认ehcache put/update via copy,因为您可以检查实现,您可以看到这些布尔值没有默认值(受保护的布尔值replicatePutsViaCopy;
),默认情况下布尔值为false,因此如果没有显式代码将其设置为true,那么它将为false-我认为我们犯了一个错误,c
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;
}
}