在锁定范围内更新地图时,Hazelcast ILock在群集中不起作用

时间:2019-01-29 07:51:37

标签: java concurrency locking hazelcast hazelcast-imap

我有一个具有2个节点(即2个JVM)的集群环境。我正在尝试检查Hazelcast ILock内部的Hazelcast IMap是否存在密钥,如下所示: 解决方案1:

public static final String CUR_ACC_MAP = "CUR_ACC_MAP";
private static final HazelcastInstance hazelInstance = Hazelcast.getHazelcastInstanceByName("accountCache");

public static boolean currencyAccountCreationInPorgress(String key) {
    ILock lock = hazelInstance.getLock(CUR_ACC_MAP);
    lock.lock();
    try {
        IMap<Object, Object> map = hazelInstance.getMap(CUR_ACC_MAP);
        if (!map.containsKey(key)) {
            map.putIfAbsent(key, System.currentTimeMillis());
            return false;
        }
        return true;
    } finally {
        lock.unlock();
    }
}

但是问题是,当在2个节点中同时调用请求时,两个节点都将进入if条件[if(!map.containsKey(key)){...}]。 因此,群集中的两个节点都从上述方法返回false。我在做什么吗?

我最初尝试使用以下代码,但该代码也不起作用,因此我切换到了上面的解决方案1,但是那也不起作用。

解决方案2:

public static final String CUR_ACC_MAP = "CUR_ACC_MAP";
private static final HazelcastInstance hazelInstance = Hazelcast.getHazelcastInstanceByName("accountCache");

public static boolean currencyAccountCreationInPorgress(String key) {
    IMap<Object, Object> map = hazelInstance.getMap(CUR_ACC_MAP);
    map.lock(CUR_ACC_MAP);
    try {
        if (!map.containsKey(key)) {
            map.putIfAbsent(key, System.currentTimeMillis());
            return false;
        }
        return true;
    } finally {
        map.unlock(CUR_ACC_MAP);
    }
}

这是我的Hazelcast配置:

    <hz:hazelcast id="hzInstance">
    <hz:config>
        <hz:instance-name>accountCache</hz:instance-name>
        <hz:group name="hzAcc" password="Vam123" />
        <hz:network port="${account.hazelcast.port}" port-auto-increment="true">
            <hz:join>
                <hz:multicast enabled="false" />
                <hz:tcp-ip enabled="${account.hazelcast.join.tcpip.enabled}">
                    <hz:members>${account.hazelcast.members}</hz:members>
                </hz:tcp-ip>
            </hz:join>
        </hz:network>

        <!-- Account File Upload Concurrent Processing Maps -->
        <hz:map name="CUR_ACC_MAP" max-idle-seconds="60" eviction-policy="LRU" max-size="100000" />

2 个答案:

答案 0 :(得分:1)

@Rajib,

  • 在解决方案2中,请尝试使用map.lock(key),即使没有锁键,它也应能工作。
  • 在解决方案1中,如果您的两个成员都是同一个Hazelcast群集的一部分,那么只有一个成员可以访问if块,而不能同时访问两者。
  • 更好的解决方案,没有锁,是这样:
public static boolean currencyAccountCreationInPorgress(String key) {
    return hazelInstance.getMap(CUR_ACC_MAP).putIfAbsent(key, System.currentTimeMillis()) != null;
}

putIfAbsent操作是原子的,因此只能成功完成一次,所有其他请求将仅返回先前的值,因此您的方法将仅返回true。

答案 1 :(得分:0)

如果您需要锁定hazalcast实例,请像这样使用,就像您试图锁定实例名称一样。请使用实例对象。它将起作用

Config cfg = new Config();
HazelcastInstance hz = Hazelcast.newHazelcastInstance(cfg);
Lock lock = hz.getLock(object_to_lock);
lock.lock();
try {
        IMap<Object, Object> map = hazelInstance.getMap(CUR_ACC_MAP);
        if (!map.containsKey(key)) {
            map.putIfAbsent(key, System.currentTimeMillis());
            return false;
        }
        return true;
    } finally {
        lock.unlock();
    }