Java - распределенная блокировка JPA для резервирования - PullRequest
0 голосов
/ 26 февраля 2019

Я работаю над устаревшей системой, которая позволяет планировать резервирование.Приложение не имеет состояния REST и предназначено для горизонтального масштабирования.База данных, однако, является общей для всех экземпляров.Прежде чем я получу лекцию по дизайну и масштабу, это не мое - нужно вынести лучшее из плохой ситуации (или кодовой базы).Недавно мы столкнулись с проблемой дублирования бронирований.Я считаю, что это из-за природы потоков ответа на запрос.Процесс в настоящее время: получение запроса, проверка базы данных на предмет противоречивого резервирования времени, если нет, вставкаВ зависимости от времени между чтением и вставкой возможно, что оба будут вставлены.Сценарий выглядит следующим образом:

|------|-------|-------|
R1     C1      I1     RSP

-|--------|-------|---------|
R2       C2     I2   RSP

Где R = Запрос, C = Проверка БД, I = Вставка.

Так что я думаю, что я мог бы использовать аннотацию @Synchronized, которая заставит всетемы для заказа.Проблема заключается в том, что запущено несколько экземпляров, поэтому они не будут работать в целом.Пессимистическое или оптимистическое чтение и запись, кажется, не применимы, так как мы пытаемся сделать комбо чтения и записи, если я полностью не пойму.Любые мысли для решения этой проблемы в масштабе?Предпочел бы обрабатывать его в Java с помощью блокировки таблиц или чего-то подобного, а не добавлять дополнительные сервисы (kafka, redis и т. Д.).

РЕДАКТИРОВАТЬ: база данных выглядит примерно так и использует h2 в dev и mysql в производстве.

 id |  start_time  | locationid | postingid | userid | durration
 --------------------------------------------------------------- 

Ответы [ 3 ]

0 голосов
/ 06 марта 2019

База данных должна обрабатывать это.Вы можете:

. Вы можете проверить свои изменения локально с помощью клиента SQL командной строки: откройте две параллельные транзакции и попробуйте разные способы чередования SELECT и INSERT. * 1015.*

0 голосов
/ 07 марта 2019

Я думаю, что логично было бы заблокировать местоположение.Если я правильно понимаю домен, вы резервируете определенное место (например, комнату) на временной интервал, заданный временем начала и продолжительностью?В этом случае у вас, вероятно, уже есть объект для определения местоположения.Если нет, то, возможно, вы можете создать его и добавить соответствующую таблицу.Тогда код будет простым:

  1. Получить пессимистическую блокировку местоположения из запроса с JPA
  2. Проверить базу данных на наличие конфликтов
  3. Вставить новое бронирование
  4. Фиксация

Блокировка таблицы действительно повредит масштабируемости, но блокировка определенного местоположения должна работать.

0 голосов
/ 04 марта 2019

Внедрение чего-то подобного с нуля - не ракетостроение, но, может быть, вы захотите взглянуть на этот проект GitHub: https://github.com/alturkovic/distributed-lock

Я не участвую в этом проекте и в настоящее время не использую его, но онвыглядит очень перспективно.Вам просто нужно создать конфигурацию Spring с помощью EnableJdbcDistributedLock:

@Configuration
@EnableJdbcDistributedLock
public class LockConfiguration {
}

и создать необходимую таблицу базы данных:

create table lock (
  id int not null auto_increment primary key,
  lock_key varchar(255) unique,
  token varchar(255),
  expireAt timestamp,
);

После этого вы можете синхронизировать вызовы методов враспределенная среда простой аннотацией (взятой из примеров проекта):

@JdbcLocked(expression = "#name")
public String sayHello(final String name) {
  return "Hello " + name + "!";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...