Hazelcast Near Cache: удалить, если изменено на другом узле

Я использую 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>

У меня подключено два клиента (оба на одном компьютере [тестовый env], используя разные порты).

Когда я меняю значение на карте на одном клиенте, у другого клиента все еще остается старое значение, пока оно не будет удалено из ближайшего кеша из-за истекшего времени простоя.

Я обнаружил похожую проблему здесь: Удаление из кэша Hazelcast не работает

Но я не уверен, действительно ли это та же проблема, по крайней мере, упоминается, что это была ошибка в версии 3.7, а мы используем 3.8.2.

Это правильное поведение или я что-то делаю не так? Я знаю, что есть свойство invalidate-on-change, но по умолчанию это true, поэтому я не думаю, что мне придется его устанавливать.

Я также пробовал установить read-backup-data на false, не помогает.

Спасибо за поддержку

Христианин


person chris922    schedule 18.05.2017    source источник


Ответы (1)


Я сам нашел решение.

Проблема в том, что Hazelcast отправляет аннулирование по умолчанию партиями и, таким образом, ждет несколько секунд, пока аннулирование не будет отправлено на все другие узлы.

Дополнительную информацию об этом можно найти здесь: http://docs.hazelcast.org/docs/3.8/manual/html-single/index.html#near-cache-invalidation

Поэтому мне пришлось установить для свойства hazelcast.map.invalidation.batch.enabled значение false, которое немедленно отправит аннулирование всем узлам. Но, как упоминалось в документации, это следует использовать только в том случае, если ожидается не слишком много операций put / remove / ..., так как в этом случае система событий будет очень загружена.

Тем не менее, даже если это свойство установлено, оно не гарантирует, что все узлы напрямую аннулируют записи ближайшего кэша. Я заметил, что после прямого доступа к значениям на другом узле иногда все в порядке, иногда нет.

Вот тест 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 всегда успешно.

person chris922    schedule 19.05.2017