Более зрелый вариант — атомарное условное списание в PostgreSQL с проверкой результата. Оно защищает общий баланс между процессами и экземплярами приложения, а не только внутри одного event loop.
Атомарное условное списание баланса в PostgreSQL
Более зрелый вариант — атомарное условное списание в PostgreSQL с проверкой результата. Оно защищает общий баланс между процессами и экземплярами приложения, а не только внутри одного event loop.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Практическое задание
Две корутины читают баланс 100, каждая списывает 80 и между чтением и записью есть await. Какое решение более зрелое?
- Логировать отрицательный баланс после списания.
- Использовать блокировку для критической секции и добавить конкурентный тест.
- Сделать списание атомарным в PostgreSQL и проверить результат операции.
- Ничего не менять: AsyncIO однопоточный.
- Убрать
awaitиз обработчика. - Проверять баланс повторно перед записью.
Ответ
Более зрелый вариант — атомарное условное списание в PostgreSQL с проверкой результата. Оно защищает общий баланс между процессами и экземплярами приложения, а не только внутри одного event loop.
Например:
UPDATE accounts
SET balance = balance - 80
WHERE id = :id AND balance >= 80
RETURNING balance;
Из двух конкурентных списаний с баланса 100 успешно пройдёт одно; отсутствие строки результата означает отказ по условию или отсутствие счёта. Для настоящего платежа добавляют транзакционный журнал и уникальный ключ операции. Локальный lock и конкурентный тест полезны, но не защищают другие процессы. Проверка после записи или повторное чтение без атомарности гонку не устраняют.