Я дописываю свой биллинг дальше, и у меня возник вопрос, может ты знаешь.
Вот есть у меня операции, которые меняют баланс, они в транзакции.
Если я обрабатываю их в один поток - то все окей, а если во много потоков - то начинаются дедлоки.
База монго, если что.
Понятно, что в рамках одного процесса я могу рассовать операции с одним аккаунтом всегда в один поток и избежать такой ситауции.
А если я хочу масштабировать апи и сделать несколько инстансов, то как быть ?
Как ты такие вещи разруливал ?
В целом это зависит от архитектуры системы и от того, может ли вообще меняться баланс одновременно (не всегда есть смысл позволять пользователю одновременное движение средств, иногда лучше либо ставить операции в очередь, либо вообще давать отлуп). Для распределённой блокировки мне пока всегда хватало redlock Часто биллинг связан с долгими внешними запросами (в банк, для примера), поэтому оборачивать все операции с балансом в транзакцию бд может быть недопустимо (долгие транзакции - зло). Тут тоже можно разрулить через redlock и/или статусы (в смысле поле в самой записи)
Оо тема транзакций, интересно. Просто мысли в слух. А если промежуточную ситуацию по транзакции писать в базу освободив ресурсы? Клиента можно держать в пендинге и детальная ситуация по транзакции останется доступной.
Со статусами так часто и делают. Упрощённый пример: необходимо сделать списание по привязанной карте, и api банка реализует списание через несколько запросов (ответ на каждый из отдельных запросов обычно приходит быстро, но для проведения списания нужно делать несколько разных запросов). Вариант реализации: создаём транзакцию бд, пишем в табличку данные списания (обязательно - ключ идемпотентности) со статусом, например, binding, делаем первый запрос к банку, при успешном ответе коммитим транзакцию в бд. Делаем второй запрос к банку, получем статус платежа, сохраняем его в бд (т.е. меняем binding на какой-нибудь committed)
Как будет в такой цепочке происходить отмена транзакции, особенно если другие мастер системы вывалились в ошибку?
Пока не понимаю что за другие мастер системы, и какие ошибки они могут выдать В примере с банком, если на первый запрос банк ответил отлупом, мы можем откатить транзакцию бд, и повторить действия через какое-то время Если банк успешно ответил на первый запрос, то на последующий (или один из последующих) он может вернуть ответ, что ничего не списал, так как на карте нет средств - этот ответ мы у себя фиксируем как конечный результат списания Если процесс (нода) упал между первым и вторым запросом к банку, после восстановления процесса мы можем ориентируясь на статусы записей в базе завершить те платежи, которые не были завершены
Ой по привычке написал) Ну в смысле внешние системы, тот же банк. В принципе цепочку действий я так и представлял.
Отмена транзакций не всегда допустима. Бывает правильнее сохранить транзакцию, указав, что она была неуспешной Для отслеживания статуса заказа в банке нужен ключ идемпотентности. Обычно в ответе на первый запрос банк выдает какой-нибудь order_id, получив который можно долбить их до ответа, получилось ли списать
Это я понимаю да, транзакция не всегда крутиться только вокруг банков. Транзакцией как сущность может быть и отгрузка товаров или что-то другое где может быть несколько "участников". Просто часто где-то описывают успешный сценарий, а про негативные сценарии почему то все забывают или рассказывают только про один, а ведь по пути транзакции может быть множество точек отказа и получается надо "откатить предыдущие шаги", а ведь даже при "откате" может быть ошибка. Сложная тема, от того и интересная)
Обсуждают сегодня