I need to implement thread-safe cluster wide counter map, so I use Hazelcast to make it cluster wide, but don't know how to make it thread-safe, I tried to use AtomicInteger, but it looks like while one thread deserialize AtomicInteger to make increment, other thread may increment and put it already back in map. So can you make some advice for me? Some sort of best practice? I think i can implement it using distributed locks, but not sure that it is best solution.
I did it using Hazelcast Distributed Task, I've implemented PartitionAware
interface so this code will be executed on the node whe counter located, so all distributed operations (lock, get, put, unlock) will be executed locally and this should enable higher concurrency.
public void track(final ip) {
try {
if(ip != null) {
executor.execute(new IncrementCounterDistributedTask<>(ip, IP_MAP_NAME));
}
} catch (RejectedExecutionException ignored) {
}
}
private static class IncrementCounterDistributedTask<K> implements Runnable, PartitionAware, Serializable {
private final K key;
private final String mapName;
public IncrementCounterDistributedTask(K key, String mapName) {
this.key = key;
this.mapName = mapName;
}
@Override
public Object getPartitionKey() {
return key;
}
@Override
public void run() {
IMap<K, Integer> map = Hazelcast.getMap(mapName);
map.lock(key);
Integer counter = map.get(key);
if(counter == null) {
map.put(key, 1);
} else {
map.put(key, ++counter);
}
map.unlock(key);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With