如何在java中锁定应用程序的redis集群

时间:2017-04-25 04:52:21

标签: java redis jedis distributed-lock

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

3 个答案:

答案 0 :(得分:4)

似乎您需要应用程序级锁来确保来自不同应用程序范围的线程安全操作,这与distributed lock非常相似。对于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 的所有者(感谢此项目),项目不再维护/拉取请求不再合并。 This fork现已得到积极维护并具有新功能:

  • SET API代替旧版SETNX
  • 使用release()
  • 上的原子LUA脚本锁定所有权安全
  • 锁定对JedisCluster
  • 的支持

答案 1 :(得分:1)

您是否尝试过Redisson锁?它是基于Redis的框架。

它提供了Lock对象实现的Component接口,并且易于使用。

export class SomeConmponent {
....

    onClickSaveProjecthandler(event) {
        const localStateProjectSettings = this.childProjectSettings.getLocalState();
        const localStateLayerFilter = this.childLayerFilter.getLocalState();

        return {
          "ProjectSettings": localStateProjectSettings,
          "Filter": localFilter
        };
      }


    render() {
        return(
            <ProjectSettingsContainer onRef={ref => (this.childProjectSettings = ref)}/>
        )
    }
}

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

答案 2 :(得分:0)

我使用Distributed locks with Redis在Jedis的竞争条件下实现了互斥 因为“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);
}