170 похожих чатов

Вопрос простой. Понятно, что если есть один сервис, который просит

списать или положить бабло, то мы просто апдейтим запись. Е сли деклаин тоже апдейтим запись
А если таких сервисов 4 или 5?
То может быть таоке что в единицу времени ежечасно я заапрувил и снял деньги для одного сервиса(то есть сперв азабронировал деньги а потмо списал), а второй раньше забронировал и потом надо списать, то уже писывать нечего так как первый списал ранее.

Конкурентое списнаие денег баланса... Что тогда делать? Это задача базы или всё же решается в коде?


Нормально написал или не? Или по другому спросить?

13 ответов

5 просмотров

Звучит как проблема дабл спендинга

Можно на уровне базы, а можно распределённые локи сделать для этого

Slava-Pinchuk Автор вопроса

Просто транзакции с разных сервисов к примеру трансфервайз , кофе Вы купили, транзакции между банковскими картами это вообще ещё один сервис и отдельная апиха. Вывод баланс надо считать один, то есть транзакции в БД становятся конкуретными и хз что с ними делать. Понятно что надо сливать всё в очередь . Рейс кондишн чтобы решаьт и решать это через мьютексы, то мне наод будет писать не 4 сервиса а монолит который слушает все 4 сервиса, тогда вариант, но думаю это дичь и писать всё же их отдельно

Slava-Pinchuk Автор вопроса
Пользователь 61a26
Через юних тайм

Сорян , а можете поконкретнее, не понял Вашу мысль. Напишите развёрнутые предложения... я не могу Вам в голову залезть, мы все мыслим по разному и это нормально.

Slava Pinchuk
Просто транзакции с разных сервисов к примеру тран...

А что мешает операции с балансом вынести в один сервис? У вас есть какое-то кол-во разных процессов со своими транзакциями, но вы ведь их потом всё равно сводите к общему виду InnerTransaction и пишете в базу. В этом случае у вас данный вопрос уже будет решаться лишь в рамках одного сервиса.

Slava-Pinchuk Автор вопроса
Kirill Penzin
А что мешает операции с балансом вынести в один се...

Вот для этого и нужны настоящие транзакции как в постгрес. Идея в том что транзакция гарантированно выполнит либо все операции, либо ничего. Ещё есть такое понятие как consistency, советую почитать потом. Есть коротко, то нужно открыть транзакцию, считать баналанс, если он ОК то вычесть в той же транзакции. Идея в том что если постгрес заметит что кто-то уже поменял баланс, то операция провалиться. ТО есть я хочу чтоб ыбаланс апедйтился в постгресе, зачем мне отдельный сервис. ПРосто я не знаю как работают транзакции которы ене завершены, например одна началасьа что вторая просит тоже начаться.. что тоггда, аналогия как с го рутинами и мьютексами? не думаю, хотся есть же согласованность атомарносьт ACID ...

SELECT … FOR UPDATE;

Slava Pinchuk
Вот для этого и нужны настоящие транзакции как в п...

Что я должен прочитать про consistency по-вашему? Вы говорите о распределённой системе, в которой хотите управлять сущностью баланса. Вам надо выдавать владение на него. Вариантов решения тут уйма. Если же не хотите распределённую, то вам всё правильно написали про БД. Вариантов разных локов — тьма.

Slava Pinchuk
Вот для этого и нужны настоящие транзакции как в п...

Зависит от уровня изоляции. На уровне SELECT .. FOR UPDATE; провала не будет, СУБД скажет ЩА ПОГОДИ

Slava-Pinchuk Автор вопроса
Kirill Penzin
Что я должен прочитать про consistency по-вашему? ...

Спасибо за любые конуструктивные мысли. Я ж не ради холивара, а ради решения спрашиваю.

Slava Pinchuk
Спасибо за любые конуструктивные мысли. Я ж не рад...

если нет претензий на распределенную БД используем СУБД и все

Slava Pinchuk
Спасибо за любые конуструктивные мысли. Я ж не рад...

Если весь процесс можно свести к транзакции в базе - надо всеми силами так и делать. Если микросервисы со своими базами или есть иные причины, из-за которых к транзакции свести нельзя - гуглить микросервисный паттерн saga. Но сочувствую.

Похожие вопросы

Обсуждают сегодня

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
DS
8
Карта сайта