Приходилось ли реализовывать очереди на Java поверх PostgreSQL
Что проверяют
Понимаете ли вы, зачем очередь делают в базе, а не в брокере, и знаете ли механизм, без которого она разваливается на втором обработчике. Разговор почти всегда сводится к одной конструкции запроса и к судьбе зависших задач.
Как отвечать
Сначала повод: очередь в той же базе позволяет записать задачу и бизнес-данные в одной транзакции. Это снимает вечную проблему «в базу записали, в брокер не успели» и закрывает большинство фоновых задач среднего проекта.
Дальше схема. Таблица с полезной нагрузкой, состоянием, временем готовности, счётчиком попыток и сроком аренды. Частичный индекс только по готовым строкам, иначе выборка со временем упирается в уже обработанные записи.
Забор пачки делается одним запросом с пропуском заблокированных строк:
update tasks set state = 'running', locked_until = now() + interval '5 minutes'
where id in (
select id from tasks
where state = 'ready' and run_after <= now()
order by run_after
for update skip locked
limit 20
)
returning id, payload;Остальное проговорите словами: обработчик обязан быть идемпотентным, потому что доставка тут как минимум однократная, повтор ставится с растущей задержкой, после исчерпания попыток задача уходит в отстойник, а будить обработчик дешевле уведомлением от базы, оставив опрос как страховку.
Где спотыкаются
Забирают задачу без пропуска заблокированных строк. Либо обработчики выстраиваются в очередь на одной и той же строке и параллелизма нет, либо выборка и обновление идут отдельно, между ними влезает сосед, и задача выполняется дважды.
Держат обработку внутри транзакции забора. Внешний вызов на минуту означает транзакцию на минуту: очистка не работает, таблица пухнет, а после падения процесса строка остаётся в работе навсегда. Аренда со сроком и возврат просроченных строк это обязательная часть, а не украшение.
Никогда не чистят таблицу. Очередь это место с очень высоким оборотом строк, и без удаления или переноса завершённых записей растут и таблица, и индекс, а частый опрос начинает стоить заметных ресурсов на ровном месте.