Александр Панков, ну даю в последний раз совет - прекращайте скакать по инструментам не изучив хотя бы что то одно. И вы не знаете минусов и плюсов MySQL но уже поскакали собирать грабли других инструментов. Нет в программировании серебряной пули. MySQL не лучше PostgresSQL, а Postgres не хуже MySQL.
А по вопросу- гуглите unique constraint causes deadlock postgresql. Не хрен в разных потоках один и тот же ключ обновлять
Eugene Usachev, называется пайплайн архитектура. у вас есть куча сервисов, которые сидят и на вход слушают свою очередь. Сервис сообщений принял запрос на публикацию сообщения, отправил на вход сервису пользователей, тот провалидировал и подписал даю добро и отправил на вход сервису чатов тот опубликовал.
вы такое в юниксе каждый раз делаете cat log.log | grep 'Error' | sort | uniq | wc -l
Eugene Usachev, реализовывал. но собственно если вы хотите сагу или двухфазный коммит - то вы вам он может потребоваться если вы добавите к вашем зоопарку сервисов например сервис rate limit который к примеру должен считать сколько сообщений в день может отправить пользователь. Тогда она у вас и будет - сервис публикации будет закоммитит сообщение тогда или только тогда когда сервис rate limit увеличит у себя счетчик сообщений пользователей и даст добро. Но конкретно в вашем случае сага нахрена? Публикация сообщения никак не должна менять состояние пользователя, а вариант обратного бан пользователя и поход сервиса пользователя по всем сервисам с криками "Вася Пупкин все!", нарушает логику сервис должен знать о работе других сервисов лишь не обходимый минимум.
Eugene Usachev, ну разделение какое то странное. Сервис пользователей и должен хранить состояние пользователей, в том числе и в каком чате он состоит. Ну даже в вашем случае - ну пускай у вас сервис сообщений залезет в сервис пользователей и проверит а не забанен ли пользователь, если нет отдаст сообщение дальше в сервис чатов который опубликует его.
Eugene Usachev, а зачем вашему сервису сообщений весь список пользователей? Ему пришло сообщение от кого то, он пошел за автором, обнаружил что он забанен, отказался публиковать. Если все ок - опубликовал. Если вы собираетесь что бы сервис сообщений держал у себя список всех пользователей - то зачем вам тогда разделение на сервисы сообщений и пользователей?
Eugene Usachev, если пользователь заблокирован раньше чем он отправил сообщение, то при отправке сообщения - оно просто не примется если на этапе сохранения сообщения вы проверяете кто и куда пишет. Как бы в чем проблема?
Eugene Usachev, нет никаких странностей. Микросервисы это вынос отдельного функционала. Иногда он никак не может быть маленьким. И тогда у вас там и папка services и aggregates и чего угодно.
Eugene Usachev, эммм. Не совсем понятно что вы хотите с блокировками. Если пользователь отправил в чат сообщение раньше чем его забанили - то оно должно появится в чате.
Виталий Артемьев,
1. Postgres умеет сжимать таблицы. Можете прописать сжатие для table space - в том числе и Lz4 как у кликхауса.
2. Сравнивать ваш кейс с таблицами и текущий кейс немножко не правильно. Ибо исходя из MVCC который в Postgres запросик вида update table set field = field; и Posgtres весело увеличит вам таблицу в 2 раза, до следующего автовакуума, не смотря на то что вроде как бы в таблице ничего не помнялось. По этому сравнивать надо не только данные, но то что вы с ними делаете - результат будет весьма различен. В этой задачи я большого количества update не вижу, поправьте меня если я не прав.
3. Почему clickhouse отдает данные быстро. Я уж лет 5 как с ним не работал, может чего поменялось, может я чего забыл, но:
a) Колоночная бд - колонки лежат в отдельных файлах. По этому запрос select field from table будет в Clickhouse быстрее чем в Postgres. Однако верно и обратное ворочать запрос вида select * from table в Postgres будет легче нежели в Clickhouse. У вас есть уверенность что первый вариант в этой задаче будет превалировать над втором? Я в этом не уверен, но с удовольствием вас выслушаю
b) Разряженный индекс вместо плотного. В Clickhouse разреженный индекс - узел индекса ссылается не на 1 запись, а на n-цать, и читает Clickhouse гранулами насколько я помню. Posgtres страницами. По этому запрос select user_id from reviews where primary between 100000 and 30000000 прекрасно отработает в Клихаусе. Верно и обратное - запрос select * from reviews where primary = 1 отработает там хуже - потому что клихаус будет искать 1 запись в грануле. Если у вас есть увереность что большая часть запросов которая в этой задаче будет соотвествовать первому варианту?
с) данные в clickhouse хранятся упорядоченно согласно первичному ключу - последовательное чтение обычно быстрее случайного. Когда вы используете clickhouse для записи каких то событий - то вообще огонь потому что события обычно идут друг за другом и использование даты в качестве первичного ключа обыденность. и запросы обычно шарашатся за даты.
Какой ключ в описанной задаче позволит нам использовать эту особенность clickhouse? И если учитывать clickhouse постоянно в фоне перестраивает таблицу какой ключ позволит кликхаусу поменьше времени тратить на сортировку?
По этому мне ваш ответ не понятен, но мне было бы интересно послушать где я косячу в своих рассуждениях.
Александр Панков, они придуманы для разных задач. И если бы ваша задача сводилась бы к тому что бы посчитать какое среднее количество отзывов добавляется по дням недели - кликхаус было бы круто. Или вы для разных выборок выбирали бы фиксированное количество колонок. Но сильное подозрение что у вас немножко другие задачи. Или вы думаете что Facebook по каким то философским причинам не может заменить все бд на колоночные?
По разному на диск пишут это как? Насколько я смутно помню что в мускуле что в постгресе по умолчанию системный fsync. А структура хранения разная да, но только это мало что меняет если вам нужно тупо записать 100Тб на диск.
З.Ы. Писал и вспомнил схожий разговор. И бац внезапно мы с вами уже о подобных вещах говорили
Александр Панков,
1. как говорит нам матушка природа скорость чего либо то ни было - конечна. И следовательно даже у NVME будет лимит по чтению и записи. И вот надо сначала смотреть упираетесь ли в этот лимит. И все эти веселья с шардированием возникли ровно потому что какую бы систему хранилища вы не выбрали - то все равно в этот лимит упретесь. Или вы думаете что Facebook по каким то религиозным причинам не может закупить себе NVME - и избавиться от тонны серверов?
2. Ну я честно говоря давно не смотрел чего там по ценам, но сильное подозрение что хранить такие данные как у вас в таком количестве на NVME - такое. Но это тоже можно посчитать - и схожим образом, у меня средняя запись весит 1кб а будет их миллиард. И обойдется это - в столько то.
3. Кликхаус бд которая хорошо работает с выборкой временных данными. А у вас оно тоже есть? Просто запрос выбери мне все отзывы у этого товара - это не работа с временными метками.
4. И еще раз. Какая хрен разница в том кто будет записывать данные на диск? Кликхаус, Постгрес или Мускул? Вы думаете они как то по разному на диск пишут? Или при использовании Clickhouse возникает сотрудник Яндекса с волшебной палочкой и дипломом хогвартса кафедра "изменения законов физики"? Или оверхед у них на сброс одной записи на диск - будет отличаться в 100 раз?
Мне кажется вам сначала стоит посмотреть на другие вещи, нежели Postgres, Kafka, партицирование. Вам стоит понять а какой вообще обьем вы пытаетесь впихнуть. То есть - вот у вас есть отзывы. Предположим в среднем отзыв 1кб, следовательно вам надо впихнуть 1000кб в секунду. Смотрите на диск - какова скорость работы. Ну если 100 кб/с - то собственно какая к черту разница Postgres или MySQL будет пытаться в игольное ушко верблюда пихать, и будет ли ему в этом помогать кафка или раббит, один хрен у вас не влезет? Тут уже смело можно смотреть в сторону шардирования. Если 10000 кб/с то вам вообщем то похрен как мускул будет у 1000 процессов индексы апдейтить, это проблемы MySQL. Нормально будет - ему то чего, если диск спокойно шуршит. А если батчем то даже и хорошо будет.
А по вопросу- гуглите unique constraint causes deadlock postgresql. Не хрен в разных потоках один и тот же ключ обновлять