Сбой блокировки JDBC Spring Integration - PullRequest
1 голос
/ 11 декабря 2019

Я не понимаю поведение распределенных блокировок, полученных из JdbcLockRegistry.

@Bean
public LockRepository lockRepository(DataSource datasource) {
    return new DefaultLockRepository(datasource);
}

@Bean
public LockRegistry lockRegistry(LockRepository repository) {
    return new JdbcLockRegistry(repository);
}

Мой проект работает на PostgreSQL, а версия Spring Boot - 2.2.2. Это демонстрационный пример использования:

@GetMapping("/isolate")
public String isolate() throws InterruptedException {
    Lock lock = registry.obtain("the-lock");
    if (lock.tryLock(10, TimeUnit.SECONDS)) {   // close
        try {
            Thread.sleep(30 * 1000L);
        } finally {
            lock.unlock();                      // open
        }
    } else {
        return "rejected";
    }
    return "acquired";
}

Примечание: этот вариант использования работает при игре с распределенными блокировками Hazelcast.

Наблюдаемое поведение состоит в том, что первая блокировка должным образом регистрируется в базе данных посредством вызова API в первом экземпляре. ,Затем в течение 30 секунд запрашивается секунда для другого экземпляра (другого порта), и он обновляет строку существующей таблицы int_lock (изменения client_id) вместо сбоя. Таким образом, первая конечная точка выполняет доставку через 30 секунд (без сбоя разблокировки), а вторая конечная точка выполняет доставку после своего собственного периода в 30 секунд. Нет взаимного исключения.

Это журналы для одного приобретения:

Trying to acquire lock...
Executing prepared SQL update
Executing prepared SQL statement [DELETE FROM INT_LOCK WHERE REGION=? AND LOCK_KEY=? AND CREATED_DATE<?]
Executing prepared SQL update
Executing prepared SQL statement [UPDATE INT_LOCK SET CREATED_DATE=? WHERE REGION=? AND LOCK_KEY=? AND CLIENT_ID=?]
Executing prepared SQL update
Executing prepared SQL statement [INSERT INTO INT_LOCK (REGION, LOCK_KEY, CLIENT_ID, CREATED_DATE) VALUES (?, ?, ?, ?)]
Processing...
Executing prepared SQL update
Executing prepared SQL statement [DELETE FROM INT_LOCK WHERE REGION=? AND LOCK_KEY=? AND CLIENT_ID=?]

Звучит странно, что процесс сбора данных начинается с DELETE, хотя ... Я попытался установитьпостоянный идентификатор клиента для DefaultLockRepository, без улучшений. Кто-нибудь имеет представление о том, как это исправить? Спасибо за любую помощь.

1 Ответ

0 голосов
/ 13 декабря 2019

Пытаясь сохранить блокировку, я попытался воспользоваться приобретением DefaultLockRepository #, вызываемым Lock # lock, которое пытается обновить перед установкой новой блокировки (и после очистки устаревших блокировок, как было сказано ранее):

@GetMapping("/isolate")
public String isolate() throws InterruptedException {
    Lock lock = registry.obtain("the-lock");
    log.warn("Trying to acquire lock...");
    if (lock.tryLock(10, TimeUnit.SECONDS)) {    // close lock
        try {
            for (int i=0; i < 6; i++) {          // very...
                log.warn("Processing...");
                Thread.sleep(5 * 1000L);         // ... long task
                lock.lock();                     //DEBUG holding (lock update)
            }
        } finally {
            if (!repository.isAcquired("the-lock")) {
                throw new IllegalStateException("lock lost");
            } else {
                lock.unlock();                   // open lock
            }
        }
    } else {
        return "rejected";
    }
    return "acquired";
}

Но это не сработало так, как ожидалось (примечание: в этом тесте по умолчанию установлено значение ttl 10 с);В конце концов, я всегда получаю исключение IllegalStateException, несмотря на то, что могу видеть изменение даты блокировки в консоли PostgreSQL.

...