Я понимаю, что ближние кэши не гарантируются для синхронизации в реальном времени, когда значение обновляется в другом месте на каком-либо другом узле.
Однако я ожидаю, что он будет синхронизирован с EntryUpdatedListener, который находится на том же узле и, следовательно, тот же процесс - или я что-то упустил?
Последовательность событий:
Кластер из 1 узла изменяет тот же ключ / значение, переключая значение с X на Y и обратно на X с интервалом каждые 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