6

我有两个 java 应用程序(app1、app2)。两个应用程序都使用JedisCluster客户端用于 Redis 集群。app1 从 Redis 集群写入或读取数据。app2 就像一个调度器,它只向 Redis 集群写入一些数据。它在固定的时间间隔后运行。我必须确保当 app2 进行写操作时,在 app2 完成整个写操作之前,不会为 app1 提供或写入任何数据。我想在 app2 运行时为 app1 锁定 Redis 集群。app1当时是否获得异常并不重要。

4

3 回答 3

5

看来您需要应用程序级锁来确保来自不同应用程序范围的线程安全操作,这与分布式锁几乎相同。对于 Jedis,快速搜索会产生Jedis-lock库。

Jedis jedis = new Jedis("localhost");
JedisLock lock = new JedisLock(jedis, "lockname", 10000, 30000);
lock.acquire();
try {
  // do some stuff
}
finally {
  lock.release();
}

System.out.println(jedis.isLocked());
System.out.println(jedis.isRemoteLocked());

编辑

根据Jedis-lock的所有者(感谢这个项目),该项目不再维护/拉取请求不再合并。这个分叉现在得到积极维护并具有新功能:

  • SETAPI 代替旧 APISETNX
  • 使用原子 LUA 脚本锁定所有权安全release()
  • 锁定支持JedisCluster
于 2017-04-25T05:10:47.280 回答
5

你试过Redisson的锁吗?这是一个基于 Redis 的框架。

它提供了 Lock 对象实现java.util.concurrent.locks.Lock的接口并且易于使用。

RedissonClient redisson = Redisson.create(config);

RLock lock = redisson.getLock("myLock");
lock.lock();
try {
   // ...
} finally {
   lock.unlock();
}

它还提供了锁对象的异步版本。

于 2017-07-19T12:22:20.207 回答
0

我已经在 J​​edis 的竞争条件下实现了互斥,将分布式锁与 Redis 一起使用, 因为“GET”不是线程安全的,因此需要在多线程环境中实现互斥锁。这是通过 getJedis() 上的 JedisSentinelPool 实现的

 public void methodWithRaceCondition() {

    Jedis jedis = getJedis();
    try {
         lock();

        //code that requires multiple exclusion on data read
        jedis.//get hget ....


    } catch (Exception up) {
        logException(up);

    } finally {
        //ALWAYS RELEASE LOCK
        releaseLock(jedis);
        closeJedis(jedis);
        jedis = null;
    }
 }

 private void releaseLock(Jedis jedis) {
    String semaphore = "SEMAPHORE";
    try {
        if (!jedis.get(semaphore).isEmpty()) {
            jedis.del(semaphore);
        }
    } catch (final RuntimeException e) {
        LOGGER_SUB.error(e);
    }
}

private void lock(Jedis jedis) throws InterruptedException {
    synchronized (this) {
        try {
            String lock = openSemaphore(jedis);
            while (lock == null || "OK".compareTo(lock) != 0) {
                this.wait(1);
                LOGGER_SUB.info("WAITED");
                lock = openSemaphore(jedis);
            }
        } catch (final RuntimeException e) {
            LOGGER_SUB.error(e);
        }
    }
}

/**
 * Distributed locks with Redis
 * https://redis.io/topics/distlock
 * Set value =1
 * NX if not exixts
 * PX for millisec
 *
 * @param jedis
 * @return
 */
private String openSemaphore(Jedis jedis) {
    return jedis.set("SEMAPHORE", "1", "NX", "PX", 30000);
}
于 2018-01-31T09:30:44.740 回答