我应该怎么做才能 bootstrap 从集群缓存对等方缓存?
What should i do so that i can bootstrap caches from cluster cache peer?
一共有三台服务器,都部署了ehcache。一台服务器由于某些原因正常或异常关闭,当我重新启动它时,我发现缓存变空并且数据丢失。当我检查时另外两台服务器,他们的缓存也变空了,数据也丢失了。我在 ehcach.org/community/ 上问过这个问题,但没有回复。我在 ehcache.org(http://www.ehcache.org/documentation/EhcacheUserGuide-1.6.pdf) 中搜索了好几天的答案,但我仍然不知道为什么。我只是找到了下面的字,但它并没有告诉我如何去做我仍然无法避免上述情况。
When a peer comes up, it will be incoherent with other caches. When the bootstrap completes it will be
partially coherent. Bootstrap gets the list of keys from a random peer, and then loads those in batches
from random peers. If bootstrap fails then the Cache will not start (not like this right now). However if a
distributed cache operation occurs which is then overwritten by bootstrap there is a chance that the cache
could be inconsistent.
下面是我的ehcache.xml
<?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
tomcat6.0.44
希望有人告诉我该怎么做,在 ehcache.xml 中配置或实现
一些 interfaces.I 在此 question.please 上花费了很多时间!!!帮助我!!!
ps: 第一次在Whosebug上提问,有什么需要的可以私信我
你基本上有 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
class如下。请注意,它有加载属性然后使用它的代码 - 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 答案,它告诉您如何自动执行此操作,否则您也可以通过一段代码手动执行此操作,以使用值加载新启动的非一致性缓存。
提示 如果您不知道如何手动操作 - 当您的应用程序启动时加载数据(从数据库或平面文件等)然后使用 cache.put
放入缓存。
一共有三台服务器,都部署了ehcache。一台服务器由于某些原因正常或异常关闭,当我重新启动它时,我发现缓存变空并且数据丢失。当我检查时另外两台服务器,他们的缓存也变空了,数据也丢失了。我在 ehcach.org/community/ 上问过这个问题,但没有回复。我在 ehcache.org(http://www.ehcache.org/documentation/EhcacheUserGuide-1.6.pdf) 中搜索了好几天的答案,但我仍然不知道为什么。我只是找到了下面的字,但它并没有告诉我如何去做我仍然无法避免上述情况。
When a peer comes up, it will be incoherent with other caches. When the bootstrap completes it will be partially coherent. Bootstrap gets the list of keys from a random peer, and then loads those in batches from random peers. If bootstrap fails then the Cache will not start (not like this right now). However if a distributed cache operation occurs which is then overwritten by bootstrap there is a chance that the cache could be inconsistent.
下面是我的ehcache.xml
<?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 tomcat6.0.44
希望有人告诉我该怎么做,在 ehcache.xml 中配置或实现 一些 interfaces.I 在此 question.please 上花费了很多时间!!!帮助我!!!
ps: 第一次在Whosebug上提问,有什么需要的可以私信我
你基本上有 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
class如下。请注意,它有加载属性然后使用它的代码 - 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 答案,它告诉您如何自动执行此操作,否则您也可以通过一段代码手动执行此操作,以使用值加载新启动的非一致性缓存。
提示 如果您不知道如何手动操作 - 当您的应用程序启动时加载数据(从数据库或平面文件等)然后使用 cache.put
放入缓存。