【问题标题】:Hazelcast ILock not working in cluster while updating map inside the lock scopeHazelcast ILock 在锁定范围内更新地图时无法在集群中工作
【发布时间】:2023-03-31 21:58:01
【问题描述】:

我有一个有 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" />

【问题讨论】:

    标签: java concurrency locking hazelcast hazelcast-imap


    【解决方案1】:

    @拉吉布,

    • 在解决方案 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。

    【讨论】:

    • 我也尝试过 map.lock(key),但没有成功。然后我切换到:map.lock(CUR_ACC_MAP)。不确定,出了什么问题。
    • 您确定两个应用节点都属于同一个集群吗?
    • 是的,两个节点都属于同一个集群。
    • 如果可能的话,您能否分享您的 Hazelcast 配置和一些显示每个节点的集群成员的日志?
    • 这是 xml 中的 hazelcast 配置:
    【解决方案2】:

    如果您需要锁定 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();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2018-08-04
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 2017-04-17
      相关资源
      最近更新 更多