Как заблокировать кластер Redis для приложения в Java

У меня есть два Java-приложения (app1, app2). Оба приложения используют JedisCluster клиент для кластера Redis. app1 записывает или читает данные из кластера Redis. app2 похож на планировщик, который только записывает некоторые данные в кластер Redis. он запускается через фиксированный промежуток времени. Я должен убедиться, что когда app2 выполняет операцию записи, никакие данные не передаются и не записываются для app1, пока app2 не завершит всю операцию записи. Я хочу заблокировать кластер Redis для app1, когда app2 работает. не имеет значения, получит ли app1 исключение или нет в то время.

3 ответа

Вы пробовали замок Редиссона? Это основанный на Redis фреймворк.

Предлагает реализованный объект блокировки java.util.concurrent.locks.Lock интерфейс и прост в использовании.

RedissonClient redisson = Redisson.create(config);

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

Он также предлагает асинхронную версию объекта блокировки.

Кажется, вам нужна блокировка на уровне приложения, чтобы обеспечить потокобезопасные операции из разных областей приложения, что во многом аналогично распределенной блокировке. Для 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(спасибо за этот проект), проект больше не поддерживается / запросы на удаление больше не объединяются. Эта вилка сейчас активно поддерживается и имеет новые функции:

  • новый SET API на месте старого SETNX
  • Блокировка безопасности владения с использованием атомарных сценариев LUA на release()
  • Блокировка поддержки для JedisCluster

Я добился взаимного исключения условий гонки на Jedis, используя распределенные блокировки с Redis, потому что "GET" не являются поточно-ориентированными, поэтому необходимо реализовать мьютекс в многопоточной среде. это было реализовано с помощью JedisSentinelPool на getJedis()

 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);
}
Другие вопросы по тегам