Java 我应该怎么做才能从集群缓存对等点引导缓存?

Java 我应该怎么做才能从集群缓存对等点引导缓存?,java,caching,ehcache,Java,Caching,Ehcache,有三台服务器,它们都部署了ehcache。一台服务器由于某些原因关闭正常或异常,当我重新启动它时,我发现缓存变空,数据丢失了。当我检查其他两台服务器时,它们的缓存也变空了,数据也丢失了。我在ehcach.org/community/上问了这个问题,但没有回答。我在ehcache.org()中搜索了好几天,但我仍然不知道为什么。我刚找到下面的单词,但它并没有告诉我怎么做,所以我仍然无法避免上述情况 当一个对等点出现时,它将与其他缓存不一致。当引导程序完成时,它将 部分连贯。Bootstrap从随机

有三台服务器,它们都部署了ehcache。一台服务器由于某些原因关闭正常或异常,当我重新启动它时,我发现缓存变空,数据丢失了。当我检查其他两台服务器时,它们的缓存也变空了,数据也丢失了。我在ehcach.org/community/上问了这个问题,但没有回答。我在ehcache.org()中搜索了好几天,但我仍然不知道为什么。我刚找到下面的单词,但它并没有告诉我怎么做,所以我仍然无法避免上述情况

当一个对等点出现时,它将与其他缓存不一致。当引导程序完成时,它将 部分连贯。Bootstrap从随机对等方获取密钥列表,然后批量加载这些密钥 来自随机的同龄人。如果引导失败,那么缓存将不会启动(现在不是这样)。但是如果 发生分布式缓存操作,该操作随后被引导覆盖。缓存有可能 可能不一致

下面是我的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 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;
    }

}