Hazelcast Near Cache:如果在不同节点上发生更改则退出

Hazelcast Near Cache: Evict if changed on different node

我正在使用 Spring + Hazelcast 3.8.2 并使用 Spring 配置配置了这样的地图:

<hz:map name="test.*" backup-count="1"
    max-size="0" eviction-percentage="30" read-backup-data="true"
    time-to-live-seconds="900"
    eviction-policy="NONE" merge-policy="com.hazelcast.map.merge.PassThroughMergePolicy">
    <hz:near-cache max-idle-seconds="300"
        time-to-live-seconds="0"
        max-size="0" />
</hz:map>

我连接了两个客户端(都在同一台机器上 [test env],使用不同的端口)。

当我在一个客户端上更改映射中的值时,另一个客户端仍然具有旧值,直到它由于空闲时间过期而从近缓存中被逐出。

我在这里发现了类似的问题:Hazelcast near-cache eviction doesn't work

但我不确定这是否真的是同一个问题,至少有人提到这是版本 3.7 中的错误,而我们使用的是 3.8.2。

这是正确的行为还是我做错了什么?我知道有一个 属性 invalidate-on-change,但默认情况下这是 true,所以我不希望我必须设置这个。

我也尝试将 read-backup-data 设置为 false,但没有帮助。

感谢您的支持

基督教徒

我自己找到了解决方案。

问题是 Hazelcast 默认情况下会分批发送无效信息,因此它会等待几秒钟,直到将无效信息发送到所有其他节点。

您可以在此处找到更多相关信息:http://docs.hazelcast.org/docs/3.8/manual/html-single/index.html#near-cache-invalidation

所以我必须将 属性 hazelcast.map.invalidation.batch.enabled 设置为 false ,这将立即向所有节点发送失效。但正如文档中所述,这应该只在没有太多预期的 put/remove/... 操作时使用,因为这会使事件系统非常繁忙。

然而,即使设置了这个属性,也不能保证所有节点都会直接使near缓存条目失效。我注意到在直接访问不同节点上的值后,有时可以,有时则不行。

这是我为此建立的 JUnit 测试:

@Test
public void testWithInvalidationBatchEnabled() throws Exception {
    System.setProperty("hazelcast.map.invalidation.batch.enabled", "true");

    doTest();
}

@Test
public void testWithoutInvalidationBatchEnabled() throws Exception {
    System.setProperty("hazelcast.map.invalidation.batch.enabled", "false");

    doTest();
}

@After
public void shutdownNodes() {
    Hazelcast.shutdownAll();
}

protected void doTest() throws Exception {
    // first config for normal cluster member
    Config c1 = new Config();
    c1.getNetworkConfig().setPort(5709);

    // second config for super client
    Config c2 = new Config();
    c2.getNetworkConfig().setPort(5710);

    // map config is the same for both nodes
    MapConfig testMapCfg = new MapConfig("test");
    NearCacheConfig ncc = new NearCacheConfig();
    ncc.setTimeToLiveSeconds(10);
    testMapCfg.setNearCacheConfig(ncc);

    c1.addMapConfig(testMapCfg);
    c2.addMapConfig(testMapCfg);

    // start instances
    HazelcastInstance h1 = Hazelcast.newHazelcastInstance(c1);
    HazelcastInstance h2 = Hazelcast.newHazelcastInstance(c2);

    IMap<Object, Object> mapH1 = h1.getMap("test");
    IMap<Object, Object> mapH2 = h2.getMap("test");

    // initial filling
    mapH1.put("a", -1);

    assertEquals(mapH1.get("a"), -1);
    assertEquals(mapH2.get("a"), -1);

    int updatedH1 = 0, updatedH2 = 0, runs = 0;
    for (int i = 0; i < 5; i++) {
        mapH1.put("a", i);

        // without this short sleep sometimes the nearcache is updated in time, sometimes not
        Thread.sleep(100);

        runs++;
        if (mapH1.get("a").equals(i)) {
            updatedH1++;
        }
        if (mapH2.get("a").equals(i)) {
            updatedH2++;
        }
    }

    assertEquals(runs, updatedH1);
    assertEquals(runs, updatedH2);
}

testWithInvalidationBatchEnabled 仅有时成功完成,testWithoutInvalidationBatchEnabled 总是成功完成。