即使Hazelcast Near Cache处于同一过程中,为什么它们也与EntryUpdatedListener不同步?

时间:2019-06-20 16:20:12

标签: hazelcast hazelcast-imap

我了解,当值在某些其他节点上的其他位置更新时,不能保证Near Cache是​​实时同步的。

但是我确实希望它与同一节点上的EntryUpdatedListener同步,因此也是相同的过程-还是我错过了什么?

事件顺序:

1个节点的集群会修改相同的键/值,每隔X秒将其值从X翻转到Y,然后再翻转回X。

客户端连接到此群集节点,并添加EntryUpdatedListener以观察翻转值。

客户端收到EntryUpdatedEvent并打印给定的值-如预期的那样,它将给出最近设置的值。

客户端立即为相同的键(应该击中附近的缓存)执行map.get,并打印一个STALE值。

我发现这很奇怪-这意味着同一客户端进程中的两个“通道”显示的数据版本不一致。我只希望在不同的过程之间能做到这一点。

下面是我的复制代码:

public class ClusterTest {
    private static final int OLD_VALUE = 10000;
    private static final int NEW_VALUE = 88888;
    private static final int KEY = 5;
    private static final int NUMBER_OF_ENTRIES = 10;

    public static void main(String[] args) throws Exception {
        HazelcastInstance instance = Hazelcast.newHazelcastInstance();

        IMap map = instance.getMap("test");
        for (int i = 0; i < NUMBER_OF_ENTRIES; i++) {
            map.put(i, 0);
        }

        System.out.println("Size of map = " + map.size());

        boolean flag = false;

        while(true) {
            int value = flag ? OLD_VALUE : NEW_VALUE;
            flag = !flag;

            map.put(KEY, value);

            System.out.println("Set a value of [" + value + "]: ");

            Thread.sleep(1000);
        }
    }
}

public class ClientTest {
    public static void main(String[] args) throws InterruptedException {
        HazelcastInstance instance = HazelcastClient.newHazelcastClient(new ClientConfig().addNearCacheConfig(new NearCacheConfig("test")));
        IMap map = instance.getMap("test");
        System.out.println("Size of map = " + map.size());

        map.addEntryListener(new MyEntryListener(instance), true);

        new CountDownLatch(1).await();
    }

    static class MyEntryListener
            implements EntryAddedListener,
            EntryUpdatedListener,
            EntryRemovedListener {
        private HazelcastInstance instance;

        public MyEntryListener(HazelcastInstance instance) {
            this.instance = instance;
        }

        @Override
        public void entryAdded(EntryEvent event) {
            System.out.println("Entry Added:" + event);
        }

        @Override
        public void entryRemoved(EntryEvent event) {
            System.out.println("Entry Removed:" + event);
        }

        @Override
        public void entryUpdated(EntryEvent event) {
            Object o = instance.getMap("test").get(event.getKey());
            boolean equals = o.equals(event.getValue());
            String s = "Event matches what has been fetched = " + equals;

            if (!equals) {
                s += ", EntryEvent value has delivered: " + (event.getValue()) + ", and an explicit GET has delivered:" + o;
            }

            System.out.println(s);
        }
    }
}

客户端的输出:

INFO: hz.client_0 [dev] [3.11.1] HazelcastClient 3.11.1 (20181218 - d294f31) is CLIENT_CONNECTED
Jun 20, 2019 4:58:15 PM com.hazelcast.internal.diagnostics.Diagnostics
INFO: hz.client_0 [dev] [3.11.1] Diagnostics disabled. To enable add -Dhazelcast.diagnostics.enabled=true to the JVM arguments.
Size of map = 10
Event matches what has been fetched = true
Event matches what has been fetched = false, EntryEvent value has delivered: 88888, and an explicit GET has delivered:10000
Event matches what has been fetched = true
Event matches what has been fetched = true
Event matches what has been fetched = false, EntryEvent value has delivered: 10000, and an explicit GET has delivered:88888

1 个答案:

答案 0 :(得分:0)

Near Cache具有“最终一致性”保证,而侦听器则以“一劳永逸”的方式工作。这就是为什么存在两种不同的机制的原因。同样,为接近高速缓存的事件进行批处理可减少网络流量,并使事件处理系统不那么忙碌(这在无效或客户端过多的情况下会有所帮助),这是折衷方案,可能会增加单个无效的延迟。如果您确信系统可以处理每个无效事件,则可以禁用批处理。

您需要在成员端配置属性,因为事件是在集群成员上生成并发送给客户端的。