
Stanislav
27.02.2018
15:59:40

Andrey
27.02.2018
15:59:53
Короче, надо навернуть атомик, ок
Пойду попробую вызвать панику при смене указателя

Alexey
27.02.2018
16:01:32
В вашем случае sync.RWMutex

Google

Alexey
27.02.2018
16:01:55
Если большинство читает

Andrey
27.02.2018
16:02:07
И то верно

Stanislav
27.02.2018
16:02:20

Andrey
27.02.2018
16:07:11
Но все же.
https://4gophers.ru/articles/konkurentnost-v-go-gonki/
Вот в статье пример, где программа с состоянием гонки не вызывает панику
(при этом, в моём вопросе не имеет значения корректность результата)
Значит ли это, что можно не заморачиваться с синхронизацией?)

Maxim
27.02.2018
16:10:57

Andrey
27.02.2018
16:11:36

Maxim
27.02.2018
16:12:23
Тогда пожалуйста

The
27.02.2018
16:13:10
И ты перед каждым запросом коннект типа поднимаешь?
С чего это вдруг? Речь идет вот о чем:
1. Пришел запрос от клиента, берем наш *sql.DB
2. В это время наша горутина устанавливает коннект и в переменную database.DB пишет то, что вернул sql.Open.
Что это? Не гонка разве?

Zver
27.02.2018
16:17:38

Alexey
27.02.2018
16:17:52

Google

The
27.02.2018
16:18:11
Какая разница что там внутри

Alexey
27.02.2018
16:18:12

Евгений
27.02.2018
16:18:55

Alexey
27.02.2018
16:19:06

The
27.02.2018
16:19:20
sql.Open() возвращает у тебя в DB, в этот момент ты берешь database.DB и обращаешься к нему.
объясните ему кто-то
когда коннект установился, понятно что внутри concurrent safe

Andrey
27.02.2018
16:20:24

Alexey
27.02.2018
16:20:49

The
27.02.2018
16:22:23
ладно, забей

Maxim
27.02.2018
16:22:27
Правда пример такого софта я не могу привести) Но есть софт где локи много выедают.

Alexey
27.02.2018
16:23:29
go-database-sql.org/accessing.html
Perhaps counter-intuitively, sql.Open() does not establish any connections to the database, nor does it validate driver connection parameters. Instead, it simply prepares the database abstraction for later use.

Andrey
27.02.2018
16:24:44

The
27.02.2018
16:25:57
ладно, забей

Alexey
27.02.2018
16:31:46
ладно, забей
Смотри https://github.com/Supme/gonder/blob/master/models/config.go#L33
Это потом используется во всём приложении и для рассылки в тысячи потоков и для статистики и для апи. Если не ограничить коннекты к базе, то база будет через какое то время делать отлуп

Andrey
27.02.2018
16:32:17
Правда пример такого софта я не могу привести) Но есть софт где локи много выедают.
Еще очень интересно как работает RWMutex.
Допустим есть 1000 горутин, которые вызвали RLock() и в этот момент читают данные.
Вызываем в другой рутине Lock(), она будет ждать пока эта 1000 дочитает, это предсказуемо.
Но в тоже время, если у нас появятся еще 500 читателей, то они будут ждать пока первая 1000 дочитает, потом, когда запишется и только потом смогут получить свои данные и это мне показалось несколько странно. Потому, что за это время уже можно ответить на запросы из тех данных, что есть.

Maxim
27.02.2018
16:33:12

The
27.02.2018
16:33:30
поднимать коннект в init, это шляпа

Google

Andrey
27.02.2018
16:34:09

Alexey
27.02.2018
16:35:21
Инит один раз происходит

Maxim
27.02.2018
16:36:47

Zver
27.02.2018
16:37:14

Andrey
27.02.2018
16:37:29

The
27.02.2018
16:37:35
Нормально работает, а тот селект 1 это проверка что не голая база
я ж говорю, в твоем случае, да, и пусть весь мир подождет, пока твой инит поднимет коннект и удостоверится. в других приложениях иногда важно не копить в пул коннекты, особенно если прет сильный трафик, твоему серверу просто не дадут подняться и разгрести всю работу. проще начать отшивать коннекты по одному, после чего, когда база поднимется, уже отвечать реальным ответом рабочим, а не ошибкой.

Andrey
27.02.2018
16:37:55

Maxim
27.02.2018
16:38:33

Zver
27.02.2018
16:38:35

Andrey
27.02.2018
16:39:59
Я сейчас либо найду информацию что указатель при состоянии гонки может повредиться, либо так и оставлю.

Maxim
27.02.2018
16:41:17

The
27.02.2018
16:42:27

Andrey
27.02.2018
16:42:54

The
27.02.2018
16:43:48
ещё разок

Maxim
27.02.2018
16:43:58

Alexey
27.02.2018
16:44:14
я ж говорю, в твоем случае, да, и пусть весь мир подождет, пока твой инит поднимет коннект и удостоверится. в других приложениях иногда важно не копить в пул коннекты, особенно если прет сильный трафик, твоему серверу просто не дадут подняться и разгрести всю работу. проще начать отшивать коннекты по одному, после чего, когда база поднимется, уже отвечать реальным ответом рабочим, а не ошибкой.
После рассылок в сотни тысяч, люди сотнями в секунду открывают письма, даже, в эти моменты рестартовали, не потеряв ни одного открытого письма в статистике, потому что когда рестартуем, http сервер не слушает, он начинает слушать когда всё готово, для клиентов это затык в сети меньше чем 100мс

Andrey
27.02.2018
16:44:31

Maxim
27.02.2018
16:49:30

Google

Andrey
27.02.2018
16:50:02
Хотя и чуть более отъедает память

Maxim
27.02.2018
16:51:25

Andrey
27.02.2018
16:53:44
Шардирование?
Нет. У нас задача как можно быстрее отдавать ответ, не меняя данные в процессе ответа.
Поэтому мы имеем "кеш" в работе, который только читается и для всех новых клиентов подменяем указатель на новый прогретый кеш.
Поэтому в существующем кеше нет состояния гонки в мапах (они только читаются) и при этом мы имеем возможность кеш обновлять.

Alexey
27.02.2018
16:54:45

Admin
ERROR: S client not available

Andrey
27.02.2018
16:55:06
Не понял вашего вопроса
Если горутины уже не будут ссылаться на старый кеш - он его соберет
Если будут ссылаться - не соберет. Логично же?

Alexey
27.02.2018
16:55:48

Andrey
27.02.2018
16:55:57

Zver
27.02.2018
16:56:36
А как вы заполняете второй кэш?

Andrey
27.02.2018
16:56:37
Указатель будет замкнут в горутине. Почему сборщик может попортить данные?
Там все медленные процессы хождения в базу и подготовки данных

Zver
27.02.2018
16:57:09

Maxim
27.02.2018
16:57:32

Zver
27.02.2018
16:57:42

Google

Andrey
27.02.2018
16:57:55
По порядку)

Alexey
27.02.2018
16:58:01
А, понял рабочая ссылка одна, а меняем её на обновлённую в которой данные, ок.

Maxim
27.02.2018
16:58:16
По порядку)
Да не, можно не отвечать уже) Я понял, тогда ваш костыль будет норм работать)

Andrey
27.02.2018
16:59:20
1. На каждый запрос мы в канал пишем id сущности которую запросили
2. В отдельной горутине канал слушаем и проверяем, что данные устарели (были обновлены n секунд назад) или вообще не сущетсвуют
3. Обновляем
4. Меняем указатель
Магия, но быстрее решения не придумал

Maxim
27.02.2018
17:01:11
Магия, но быстрее решения не придумал
а bigcache пробовали? Я не уверен что он быстрее, но он очень интересно хранит данные в одной куче и по оффсетам достает. Должно быть очень быстро и конкуретно)

Andrey
27.02.2018
17:01:45

Zver
27.02.2018
17:03:12

Andrey
27.02.2018
17:03:16
а, кстати, я его изучал. Шардирование - тоже рассматривали как вариант. Но он внутри все равно с лочками. И в нашем варианте выглядит все проще.

Alexey
27.02.2018
17:03:44
А какая нагрузка то?

Andrey
27.02.2018
17:04:17

Zver
27.02.2018
17:05:51
Почему?
Потому что запись в канал блокирующая операция (в которой, кстати мютексы используются) и пока данные не изымут из канала горутина будет висеть. Либо делать буфер с запасом.

Andrey
27.02.2018
17:05:52
В проде сейчас в среднем 800 запросов в секунду, но там пхп и тоже все оптимизированно, что даже на 10% проц не грузит.

Alexey
27.02.2018
17:05:53
Гошка с шаблонами штатными гигабитный канал запросто забивала, причём был ещё xorm но с включеным кэшем

Andrey
27.02.2018
17:06:11

Zver
27.02.2018
17:07:03

Andrey
27.02.2018
17:07:06
Покажите.
select{
case ch <- id:
case default:
}