
Александр
29.07.2018
15:21:36
стопэ
вы какую задачу решаете?

andrew
29.07.2018
15:22:16
Состояние гонки между горутинами и внешней бб
Бд

Google

Александр
29.07.2018
15:22:59
эм, может быть имеется введу гонка на уровне бд?
например есть баланс вы его выбираете и тут-же обновляете в следующем запросе
если вы делаете это в двух гоурутинах то получится фигня
но это состояние "гонки" уже внутри бд решается
транзакциями

andrew
29.07.2018
15:24:01

Александр
29.07.2018
15:24:10
в чем она заключается то?

andrew
29.07.2018
15:26:05
В том что пока совершается неблокируемый вызов бд, одна горутина засыпает и просыпается другая. Если другая горутина аналогична первой она сделает тот же запрос, затем просыпается первая горутина и прибавляет деньги и ставит пометку об оплате, просыпается вторая и делает то де самое так как результат соответствовал первому запросу и тоже приьавляет деньги

Александр
29.07.2018
15:27:33
очень странный концепт, можно каких то подробностей? зачем у вас две гоурутины прибавляют деньги

andrew
29.07.2018
15:28:02
Если каждый запрос будет оьрабатываться в горутине то то же самое прлучится

Vladislav
29.07.2018
15:29:14
Есть два варианта, в зависимости от того, как устроено приложение и может ли у вас БД быть хранилищем логики:
1. Делаете бизнес-операцию атомарной на уровне приложения, например, обрабатывая все запросы на эту операцию через каналы
2. Делаете эту бизнес-оперцию на уровне БД, используя транзакции (стоит вниматально выбрать уровень изоляции), например, в хранимке

andrew
29.07.2018
15:30:12
А я думал про мьютексы

Google

Александр
29.07.2018
15:30:28
что бы давать советы, надо понимать бизнес задачу
я просто нюхом чую что там что-то не так с логикой

andrew
29.07.2018
15:30:48
Например приходит запрос на пополнение, мы юзера заносим в мьютекс и другие пополнения этого юзера ждут
А других юзеров выполняются асинхронно
То есть синхронное выполнение в рамках одного юзера

Александр
29.07.2018
15:31:36

Zver
29.07.2018
15:31:37
Замучаетесь это мютексами регулировать.

Александр
29.07.2018
15:31:43
и нам это скармливаете как "несколько гоурутин"

andrew
29.07.2018
15:31:57

Александр
29.07.2018
15:32:09
уже ближе
а вебсокет на стандартной либе?

andrew
29.07.2018
15:32:16
Просто обычный тсп сокет. Каждый пакет от юзера обрабатывается в горутине

Александр
29.07.2018
15:33:07
я как понял так, вы слушаеет вебсокет и от клиента приходит несколько пакетов
причем там есть дубли
так?

andrew
29.07.2018
15:33:31
Отправляем подряд несколько пакетов на пополнение и получаем гонку
Как выше описал

Александр
29.07.2018
15:33:50
вам как надо?

Zver
29.07.2018
15:34:07
А какая ДБ?

Google

Александр
29.07.2018
15:34:08
что бы несколько пакетов обработали корректно или проигнорировать "дубли" пакетов?

andrew
29.07.2018
15:34:38
Семафоры мб?

Александр
29.07.2018
15:34:53
да стойте
какие семафоры
если у вас клиент ДУБЛИРУЕТ пакеты

Zver
29.07.2018
15:35:32
Ну тут, либо все перации на изменение ставить в поток, чтобы не было несогласованности, либо на уровне бызы изолировать.

Vladislav
29.07.2018
15:35:51
Кажется, что тут нет разницы в том, откуда идут запросы и зачем. Важно то, что есть критическая секция и ее нужно выполнить один раз корректно, а остальные попытки либо отправить домой с ошибкой, либо идемпотентно вернуть тот же резульат что и при удачном выполнении

andrew
29.07.2018
15:35:52
Лол ну трабла не в дублях. Я могу сформировать второй и третий пакет на другие суммы
И они пройдут проверку
Трабла в гонке

Александр
29.07.2018
15:36:45
заверните в транзакцию
в чем тогда проблема?

Zver
29.07.2018
15:36:52

andrew
29.07.2018
15:37:17
Транзакции на уровне бд происходят. Mysql. А проверка проходит в гоу
Как вариант это перенести в хранимки

Александр
29.07.2018
15:37:33
какая проверка то?

andrew
29.07.2018
15:37:42
А на стороне гоу можно что-то придумать

Александр
29.07.2018
15:37:53
у вас:
Открыл транзакцию
select
insert
Закрыл транзакцию

Google

Александр
29.07.2018
15:37:58
коммит
в зависимости от уровня изоляции это будет работать по разному

andrew
29.07.2018
15:38:35

Vladislav
29.07.2018
15:38:43
еще может помочь select for update

andrew
29.07.2018
15:38:44
При коммите нет проверки на легетимность

Zver
29.07.2018
15:38:52

andrew
29.07.2018
15:40:10
Да я знаю транзакции)
Они тут не помогут
Выше уже отписал
Либо в хранимки переводить
Либо какие-то хитрые мьютексы пилить
Или семафоры
Для конкретного действия юзера
Чтобы одновременно не происходило 2 действия

Vladislav
29.07.2018
15:41:42
ну тогда воспользуйтесь select for update
если хотите сделать средствами бд
сначала считаете, потом обновите

Zver
29.07.2018
15:41:58
Про изоляцию в MySQL
https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

Александр
29.07.2018
15:42:15

andrew
29.07.2018
15:43:20

Google

Александр
29.07.2018
15:43:35
одну запись

andrew
29.07.2018
15:43:50
Хм, ну тоже как вариант

Александр
29.07.2018
15:44:03
но вообще при работе с балансом в банке так и не делают никогда

andrew
29.07.2018
15:44:20

Александр
29.07.2018
15:44:33
делают табличку с транзакциями на insert, и баланс выводят на основе суммы по колонке
никаких update

andrew
29.07.2018
15:45:09
А ну я понял, транзакции в нормализованном виде, баланс в денормализованном

Александр
29.07.2018
15:45:19
каждое списание/пополнение - отдельная транзакция

andrew
29.07.2018
15:45:19
Платежные транзакции*

Александр
29.07.2018
15:45:31
таким образом легко поправить с любого места
даже если кто-то списал 1 миллион долларов
мы просто анулируем 1 транзакцию и все

Pawel
29.07.2018
15:47:11
Хотя должна только одна)
Тут Александр опятьразвёл какое то страшное ужасное словоблудие ни о чём. В чём конкретно проблема ваша проявилась?

andrew
29.07.2018
15:48:16
Но уже есть варианты решения с бд

Pavel
29.07.2018
15:49:18
Вам про уровни изоляции выше написали правильно, кажется.

andrew
29.07.2018
15:50:02
Ну да. Как вариант. Я думал что можно как-то в гоу решить
Но с бд тоже норм

Александр
29.07.2018
15:50:48
вот тут посмотрите