Как эффективно ждать, пока данные станут доступными в таблице RDBS (PostgreSQL)? - PullRequest
0 голосов
/ 14 марта 2020

Я создаю веб-сервис, который резервирует уникальные элементы для пользователей.

Сервис необходим для обработки большого количества одновременных запросов, которые должны избегать максимально возможной блокировки друг друга. Каждый входящий запрос должен зарезервировать n уникальных элементов нужного типа, а затем успешно обработать или вернуть их в список резервируемых объектов, чтобы они могли быть зарезервированы другим запросом. Успешная обработка включает в себя несколько этапов, таких как обмен данными с интегрированными службами и другие этапы, требующие много времени, поэтому сохранение элементов, зарезервированных для транзакции БД, до конца не будет эффективным решением.

В настоящее время я реализовал решение, в котором резервируемые элементы хранятся в буферной таблице БД, где элементы блокируются и удаляются входящими запросами с помощью SELECT FOR UPDATE SKIP LOCKED. Поскольку служба должна поддерживать несколько типов элементов, эта буферная таблица содержит только n элементов в каждом типе за раз, так как в противном случае размер таблицы слишком велик, поскольку существует около десяти тысяч различных типов. Когда все типы элементов зарезервированы (выбраны и удалены), запрос блокирует тип элемента и добавляет больше резервируемых элементов в буфер. Эта операция заполнения требует вызовов интеграции и может занять некоторое время. Во время заполнения все остальные операции должны ждать, пока операция заполнения не завершится и элементы не станут доступными. Вот где возникает проблема. Когда тысячи запросов ждут, пока один и тот же тип элемента станет доступным в буфере, каждый из них должен как-то опросить эту информацию.

Что может быть эффективным решением для такого рода опросов?

1 Ответ

0 голосов
/ 14 марта 2020

Я думаю, что «реальный» ответ - начать процесс пополнения, когда запас становится низким, а не когда он полностью истощается. Тогда он уже будет пополнен к тому времени, когда кому-то понадобится заблокировать его. Или, возможно, вы могли бы заставить процесс пополнения работать асинхронно, чтобы новые строки генерировались почти мгновенно, а затем вызывались интеграции. Таким образом, вы ставите в очередь интеграцию, а не потребителей.

Но, исключая это, кажется, что вы хотите, чтобы официанты блокировали «тип элемента» в режиме, несовместимом с тем, как блокировщик перезагружает его. Затем он естественным образом заблокируется и будет выпущен после завершения добавления наполнителя. Проблема в том, что если вы хотите собрать порядка 50 вещей, а 47-й истощается, хотите ли вы сохранить резервирование для предыдущих 46 вещей, пока вы ждете?

Предположительно, ваше бронирование не блокирует кого-либо еще Если только тот, который вы зарезервировали, не будет последним доступным. В этом случае вы на самом деле не блокируете их, просто заставляете их go через процесс пополнения, что в любом случае должно было бы быть сделано в любом случае.

...