LINUX.ORG.RU

Пишем мессенджер. Подумаем об архитектуре БД для черновиков.

 


0

2

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

  • MESSAGE - хранит сами сообщения; это особая база, она хранит каждый чатик как вектор объектов Message, больше ничего не умеет. Зато умеет зверски быстро отдать любой подинтервал любого чатика или вставить мессагу в середину чатика длиной миллиард месаг за микросекунду.
  • LIKES - хранит лайки к чему-то, может вернуть число лайков под каким-то объектом по его ID, больше ничо не умеет. Ну и умеет гарантировать, что ты не лайкнул что-то 2 раза. Реакции короче.
  • ACCOUNT - хранит профили юзеров. Пароли там всякие, ID фотки аватара и что-то такое.
  • SESSION - хранит куки или какие-то залогиненные сессии; Буквально это хештаблица sid=uid.
  • ATTACH - хранит инфу про аттачи; буквально хештаблица attach_id = (кодовое filename в хранилище файликов, автор аттача, когда запощено, тип аттача, что-то ещё..)
  • ATTACH_HASH - хранит хеши известных файлов, дедупликация аттачей, чтобы 2 раза одно и тоже не хранить
  • ATTACH_UID - обратный индекс для аттачей uid=[список всех аттачей этого юзера, чтобы можно было все экстремистские материалы сразу майору слить когда террориста поймали]
  • LIBRARY - информация про чатики или группы или каналы. Длинный профиль и настройки чатика. Буквально хештаблица chat_id = (структура данных про этот чатик рассказывающая - кто создал, когда, полное имя, полное описание, аватарка, флаги разрешённых действий с чатиком, список модеров и владельцев и прочая херобаза)
  • CONTACTLIST - контактлисты юзеров. Ты в чатик зашёл, тебе его в контактлист захерачили. В мессенджер вошёл - твой контактлист вычитали и тебе вернули, чтобы ты мог в свои чатики или в свои контакты смотреть.
  • и т.п. Разных баз около 20 под каждый пук.

И тут мы захотели сделать черновики. Ну короче, запилили базу DRAFT и запилили функционал в клиента и в сервер. Набираемое в поле ввода периодически отправляется серверу, сервер это кладёт в отдельную базу «DRAFT». Когда клиент умер и переподключился, то открыв данный чатик ему подгрузят из DRAFT что он там набирал и он может продолжить. Всё как-бы хорошо, но есть приколы.

  1. Раньше постинг мессаги предполагал на backend 1 запрос в базу MESSAGE - запостил и готово, а теперь 2 запроса - надо ещё удалить эту мессагу из DRAFT.
  2. Если DRAFT упала и там что-то было, а ты уже запостил, то потом внезапно клиенту восстанет из ада старый черновик. Возможно это чем-то хорошо, ну мол лучше данные сохранить, чем потерять, но всё равно странновато.

Потом возникла идея, которую надо обсудить.

  1. Выкинуть базу DRAFT и сохранять черновик в базу MESSAGE в отдельную табличку в той же шарде. Когда юзер постит, сделать хитрее: выполнить в базе особо хитровыдуманную атомарную команду «move» которая атомарно-транзакционно переместит черновик как он есть в таблицу сообщений (тут предполагается, конечно, что мы доводим черновик перед этим до состояния финальной мессаги, то есть досылаем в черновик те изменения, которые юзверь сделал после последнего SAVE_DRAFT и до MSG_SEND). В постгресе такой «move» бы наверно делался как небольшая транзакция вида "BEGIN; вставить в MSG результат подзапроса из DRAFT; delete from DRAFT; COMMIT;). Решается сразу проблемы (1) и (2).

Но тут возникла такая приколюха:

  1. Если раньше база MESSAGE была нагружена на запись только тем, что туда постили финальные мессаги, то теперь каждые 2 секунды туда будет апдейт черновика от каждого кто печатает. То есть, это сразу кратный рост нагрузки в разы. Прям в разы. Потому что для каждого «поста» финального сообщения в чатик, который совершался и раньше, теперь этот пост ещё льётся нам каждые 2 секунды в эту базу в отдельную табличку апдейтом. Теперь если посмотреть на пишущую нагрузку в базу MESSAGE то добавление финальных сообщений в неё - это теперь не основная нагрузка, основная - куча апдейтов черновиков.

Короче как лучше не понятно. Ужирнить MESSAGE и забить болт или всё таки юзать схему с отдельной базуней DRAFT?



Последнее исправление: lesopilorama (всего исправлений: 1)

Я думаю, что вы делаете что-то не так.
Дано:

  • вы русский человек, рассуждающий на русском языке.
  • вам нужно построить конструкт для достижения каких-то целей.
  • для описания конструкта вам нужна онтология (список слов).

И тут ни с того, ни с сего MESSAGE.

Можно, но зачем? Есть же слово ТЕКСТ.

Saakx
()
Ответ на: комментарий от KivApple

Если клиент видит в диалоге сообщение с тем же UUID,

Проблема в том, что заходя в чатик через день, клиент видит только последние, скажем, 32…64 месаги, а всё более старое подгрузит только если будет скроллить наверх. А его месага последний раз отправлялась 4096 мессаг тому назад и ничего своего в чатике он «сразу» не увидит.

lesopilorama
() автор топика
Ответ на: комментарий от Shadow

А сделай update каждые два пробела либо 5 секунд (в смысле и то, и то по OR). Будет иллюзия полного сохранения и терпимая нагрузка.

Да, там понаворочано на эту тему:

  1. Каждое изменение поля ввода в клиенте - это инкремент в клиенте uint32_t state; для этого поля ввода.
  2. Если разница state - state_saved дошла до ~150 - принудительно прямо щас отправить черновик. Сервер на такую отправку отвечает некий draft_state(S) ответ, в котором написано какой S = state сервер видел. Мы сохраняем себе state_saved = S. Короче, принудительное сохранение если изменений накопилось «много».
  3. Если от конца последнего нажатия на кнопку прошло сколько-то «много» времени (захардкожено что-то там, не помню), то делать попытку сохранить черновик.
  4. Если попытка сохранить произошла почему-то раньше чем через «слишком мало миллисек» (что-то захардкожено) после предыдущей попытки - ничего не делать, даже если было вызвано причиной (2). Тут ещё дело в том, что эти попытки запускаются асинхронно по таймеру, что позволяет реагировать примерно на всё - и на критическое число изменений и на то, что «слишком давно не печаталось».
  5. Если при попытке сохранить (по любой причине, например «слишком давно не печаталось») разница state - state_saved равна нулю, то тоже ничего не делать.

Это длинное описание 2-3 ифов в коде.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)

Что бы я сделал.

  1. Отправляй только изменение. Не нужно слать весь черновик каждый раз. Почитай как работает Гугл докс.
  2. Перед базой поставь очередь. Она агрегирует изменения и может периодически пушить полный черновик в БД.
  3. Черновиком может быть тот же message со специальным флагом «не опубликовано» и constraint, что такая запись на «отправитель, чат» может быть только одна.
  4. Теперь пользователь не отправляет сообщений. Он создает черновик, который, при нажатии «отправить», превращается в опубликованное сообщение атомарным изменением флага.

Так ты сильно разгрузишь базу и получишь дополнительный слой масштабирования.

anonymous
()
Ответ на: комментарий от Saakx

Это абсолютно два разных слова, если что. С разными значениями. В русском очень много заимствований.

И если уж на то пошло, ты зачем, рассуждающий на русском языке написал конструкт, онтология, текст? Неужели не нашлось русских слов для подтверждения точку зрения?

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от anonymous
  1. Да, были такие мысли. Но чё-то сложно-сложно на первом этапе. Есть всякие краевые фигни. Юзер вставил кусок текста в середину и одновременно ловко в конце точку поставил. Хоба, оно должно уметь уже нетривиальные диффы какбэ.
  2. Да, вот это интересная идея. Была такая идея, в backend-процессе, к которому юзер держит коннект (а коннект может быть долгим и процесс, держащий его, живёт долго) можно в памяти складировать без базы. Надо это проработать. Вероятность того, что этот процесс сдох - не выше, чем собственно процесс «СУБД», с чего ему быть выше-то по идее, если сделано не граблями. Ну может и чуть выше, потому что всё-таки это «бизнес-логика», а её принято пилить костылями почему-то.
  3. Сложно реализуемо чисто по принципу устройства наших баз, ну точнее я это пытался описать в первом посте. Там у меня эта запись лежала в отдельной табличке-хештабличке, где она может быть только одна, а потом база САМА её перекладывала по команде «move из одного в другое» - тут надо базу чуть подпилить.
  4. Да, такая тема была, обсуждалась, в стартовой месаге этому уделено вним., либо кому-то отвечал про это. Но ещё до написания топика была такая мысль, да - собственно это тот вариант, который описывается «кладём черновики в базу MESSAGES, а при постинге делаем атомарный MOVE из одной таблицы в другую». Тут дублирую сказанное в (3).

Идея с «очередью» тут конечно самая годная. Точнее не очередь, а тупо хештабличка вида [(uid, chat_id)] => Message в памяти backend процесса, который сейчас держит коннект к этому клиенту. Процессов таких конечно может быть много, ибо может быть пошардено-пореплицировано ради нагрузки. Message - это черновик. Досылы этого черновика просто апдейтят эту [(uid, chat_id)] => Message в памяти. Процесс упал - черновики просраны за последнюю минуту. Но тут дело такое: «чо бы ему падать-то, пишите код без ошибок, базу же написали как-то».

В целом да, интересное направление: за счёт известной степени необязательности-роскошности фичи «черновики» можно расплатиться за вероятность падения backend-процесса, который черновики держал в RAM… Быстро, дёшево, модно, базу не пинают.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 2)
Ответ на: комментарий от lesopilorama

А мне понравилась идея про «юзер прекратил печатать». Ждем некоторое время (да даже несколько секунд) и потом сохраняем. Запомнил для себя - так и сделаю, наверное.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от anonymous

ТС, если твой проект не макс, то разочарую, его всё равно забанят. Потому что задача макса не просто быть отечественным, а быть единственным. На это вагон причин, а единственная причина почему этого не должно быть - конкуренция, но макс не про конкуренцию. Начну с простого вопроса: что легче контролировать и проще находить виновных, даже скажем от утечек персональных данных: один единственный мессенджер или 100500 разных пусть даже физически они все у тебя? Ответ - один единственный. Вот смотри, если оставить в стране только ГУМ из магазинов, то там просто проконтролировать чтоб водку и сигареты не продавали несовершеннолетним. А сейчас всё равно продают, только не Пятёрочки, а всякие магазины поменьше. Так и тут.

anonymous
()
Ответ на: комментарий от LightDiver

А мне понравилась идея про «юзер прекратил печатать». Ждем некоторое время (да даже несколько секунд) и потом сохраняем. Запомнил для себя - так и сделаю, наверное.

Да, это интуитивно понятно. И много где наблюдается. Ещё были вопросы по UI - не было ясно как оповещать юзера, что черонвик сохранился. Думал-думал, пришёл к выводу, что лучше вообще НИКАК. Как телега. Просто сохраняй, не надо мозолить глаза об этом. Лучше потом покажи сохранённый - и будет понятно, что ты молодец. Уместно оповещать в веб-версии большого текстового редактора, где люди привыкли на дискетку нажимать, а тут не надо)

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 2)

И тут мы захотели сделать черновики. Ну короче, запилили базу DRAFT и запилили функционал в клиента и в сервер. Набираемое в поле ввода периодически отправляется серверу, сервер это кладёт в отдельную базу «DRAFT». Когда клиент умер и переподключился, то открыв данный чатик ему подгрузят из DRAFT что он там набирал и он может продолжить. Всё как-бы хорошо, но есть приколы.

Раньше постинг мессаги предполагал на backend 1 запрос в базу MESSAGE - запостил и готово, а теперь 2 запроса - надо ещё удалить эту мессагу из DRAFT.

на мой взгляд over-engeniring во все поля, ну да это ваше дело, с ваших слов всё работает :-)

после впиливания DRAFT, постинг мессаги со стороны клиента это не «послать в одну базу и удалить из другой», а «перенести UUID (и всё что с ним) из DRAFT в MESSAGES». Запрос со стороны клиента всё равно один. Если базы умеют такие транзакции, то ok. Если нет, значит наоборот.

и прекрасные грабли конечно будут: что делать клиенту если связь отвалилась (вообще, или с одной из баз), что делать серверам когда упала-поднялась одна из баз.

энтерпрайз должен быть энтерпрайзом: добавляйте ещё одну базу: TRANSFER - отвечающую за перенос данных из DRAFT в MESSAGES

всей команде разработчиков найдётся работа при грамотном менеджере проекта :-)

MKuznetsov ★★★★★
()

Слишком много труда и слов ради, на первый взгляд, малонужной фичи. Если нужна «площадка» для хранения черновиков, то не проще ли использовать для этих целей некоторый аналог чата «Избранное»? Оно и куда более целостным ощущается и куда менее оверинжиниринговым. Мне, правда, интересно - вы по результатам анализа пришли к тому, что оно нужно? Или просто хочется чем-то интересным заняться в отсутствие более актуальных задач?

verdammter_katze
()
Ответ на: комментарий от lesopilorama

Сервер может выдавать юзеру UUID последней отправленной им мессаги в каждый чат. Ну и ещё надеятся на то, что сервер успеет удалить черновик, пока сообщение юзера уползёт вверх (когда бекэнд получает команду на отправку сообщения, он после вставки сообщения в MESSAGES, удаляет его из DRAFTS, даже если это не одна транзакция, в любом случае между двумя операциями пройдут секунды, а на случай краша бекэнда можно предусмотреть очередь операций, которая обеспечит ретрай удаления).

А вообще у меня есть ощущение, что ты просто придумываешь себе проблемы. Используй БД с транзакциями (не вижу смысла шардить по таблицам, а не по юзерам или чатам, например) или накостыль транзакции поверх.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 2)

Нагружать базу сообщений постоянными обновлениями кажется однозначно плохой идеей: вы создадите паразитную нагрузку на БД, т.к. в реальности хранить 99.9% черновиков персистентно НЕ НУЖНО (юзер написал, отправил и забыл).

Ваши черновики звучат как задача для in-mem базки (типа Redis, Dragonfly etc.) + персистентность для черновиков, которые действительно надо хранить. То есть «в реальном времени» пишем только в in-mem, а в персистентное хранилище черновиков флашим по какому вам нужно алгоритму. Например, когда мы уверены, что юзер перестал редактировать текст и его надо оставить в системе на будущее.

Вопрос, по большей части, в том, как правильно организовать в системе транзакцию публикации сообщения из черновика, что вы правильно обозначили в первоначальном посте.

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

paddlewan
()
Ответ на: комментарий от MKuznetsov

и прекрасные грабли конечно будут: что делать клиенту если связь отвалилась (вообще, или с одной из баз), что делать серверам когда упала-поднялась одна из баз.

Переконнектиться, запросить сохраненный черновик и печатать дальше. Вообще не понял проблемы.

lesopilorama
() автор топика
Ответ на: комментарий от paddlewan

То есть «в реальном времени» пишем только в in-mem, а в персистентное хранилище черновиков флашим по какому вам нужно алгоритму.

Да, всё верно, к этому решению видимо и приходим. Причём, даже без отдельного redis, а прямо в памяти того процесса, к которому держали коннект.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от paddlewan

Вопрос, по большей части, в том, как правильно организовать в системе транзакцию публикации сообщения из черновика

Если хранить черновики inmem, то как раз не сложно: запрос SEND_MESSAGE(chat_id, text) по TCP соединению от клиента пролетает через ту же структуру данных, которая и черновики хранила и вообще отвечает за текущую TCP-сессию этого чела. Код, который запишет сообщеньеу в базу, сразу из памяти забудет и черновики.

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

даже без отдельного redis, а прямо в памяти того процесса, к которому держали коннект.

Об этом решении вы очень пожалеете, если нужно будет масштабировать решение горизонтально. Так вы завяжете систему на то, что входная точка (внешний API) - это строго один процесс. Не знаю, под какие нагрузки все это у вас должно быть рассчитано, но долгосрочно решение, кмк, не очень, если система будет развиваться.

Я бы все же подумал об отдельно стоящей in-mem базке.

paddlewan
()

1. Удаляете из драфта. Сохраняете в месседж. Продолб драфта в процессе факапа юзер перетерпит.

2. В следующий раз делаете нормальную базу и не страдаете хернёй на каждый пук.

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 2)
Ответ на: комментарий от paddlewan

Об этом решении вы очень пожалеете, если нужно будет масштабировать решение горизонтально. Так вы завяжете систему на то, что входная точка (внешний API) - это строго один процесс

Процессов входных сотня. Об этом подумали. При коннекте на другой, мы получим черновик из базы, какую-то его слегка отсталую версию. Ибо процессы раз в минуту-то что-то в базу закидывать должны. Но есть даже решение интереснее. Оно через тот же механизм, через который 100 сидящих в одном чатике через разные фронтенд-сервера видят широковещатнльные мессаги друг от друга. Через это пробросить. То есть, когда ты законнектился в сервер 57, и у тебя uid 5555, то сервер 57 в специальном сетевом пошарденном координаторе для юзера 5555 сохраняет инфу о том, что этот юзер есть/недавно был на сервере 57. Тогда законнектившись потом в другой сервер 81 как 5555 ты сходишь из 81 на 57 и достанешь последний черновик, если был.

lesopilorama
() автор топика
Ответ на: комментарий от ya-betmen
  1. В следующий раз делаете нормальную базу и не страдаете хернёй на каждый пук.

По какой-то причине телеграм не хранит мессаги чатов в постгресе. Это капец тормоза и поедание ресурсов впустую. У меня уже вся бизнес-логика отработает пока постгрес будет запрос парсить и строить план исполнения…

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от paddlewan

Кхм, ну странное же. А это вы так хотите чтобы что? Просто чтоб редиску не поднимать?

Это проще, чем редиску поднимать и содержать. Одна новая структура данных и меньше сетевых хопов. За лишнюю микросекунду отца родного продадим.

lesopilorama
() автор топика
Ответ на: комментарий от paddlewan

Я бы все же подумал об отдельно стоящей in-mem базке.

Строго говоря, все на свете базки - inmem. У постгресов и InnoDB всяких все нужные страницы B+-деревьев всё время впамяти, максимум нет какой-то одной.

lesopilorama
() автор топика
Ответ на: комментарий от ya-betmen

Любую с транзакциями

В реальности, никакая ОДНА база не вывезет большие нагрузки. Поэтому, к сожалению, ваш подход хорош до определенного (очень небольшого) предела. Дальше базка будет тормозить и придется думать головой, как это все развязывать и разносить по разным СУБД.

Вот таких кейсов в реальном мире просто полно :)

paddlewan
()
Ответ на: комментарий от lesopilorama

По какой-то причине телеграм не хранит мессаги чатов в постгресе.

Хз, я не видел серверный код телеги.

У меня уже вся бизнес-логика отработает пока постгрес будет запрос парсить и строить план исполнения

Или скорее ты просто создашь кучу паразитного сетевого траффика и рандомных тормозов.

ya-betmen ★★★★★
()
Ответ на: комментарий от paddlewan

Реальность такова что с одной стороны да, для любой базы будет существовать предельная нагрузка которую она не выведет. Но с другой стороны делая чятик в этот предел упираются только любители хайлоада.

ya-betmen ★★★★★
()

Короче как лучше не понятно.

Ну почему же, понятно: лучше всего выкинуть всю эту архитектуру сразу. Я сильно в эту лапшу не вчитывался, но сходу видно:

  1. Нет транзакций, а это сразу мусор в данных. Гуглите distributed transactions.

  2. Тоже самое с вложениями, зависшие файлы в хранилище, неизвестные отправители и тд. Гуглите тоже самое еще раз, но для файлов.

  3. Оверхед по запросам на ровном месте, вместо обычных join выполняются запросы ко всем базам последовательно, сначала запрос на список контактов, затем запрос на получение профилей этих контактов, показ их последних сообщений - третий запрос и тд. Гуглите SQL Joins.

  4. Такое количество распределенных баз это рай для девопса, но ад для проекта. Ему всегда будет чем заняться. Если вы девопс то гуглить бесполезно.

  5. Шардинг-ключи не согласованы между базами. Сообщения шардируется по chat_id, а лайки по чему шардируются? По message_id? Тогда при рендере чата лайки к сообщениям разлетаются по разным шардам LIKES. И для корректного сбора нужно реализовать шаблон scatter-gather, гуглите его.

  6. Если MESSAGE хранит «вектор объектов», то объекты содержат что? Если объект содержит текст + автор + аттачи + лайки, то при обновлении лайка надо перезаписывать запись в MESSAGE? там у нас микросервисы, а тут рыбу заворачиваем? Гуглите Coupling (связанность) между базами данных.

Это архитектура уровня студента второго курса. LLM сделает лучше.

Obezyan
()
Ответ на: комментарий от lesopilorama

Переконнектиться, запросить сохраненный черновик и печатать дальше. Вообще не понял проблемы.

вы вообще что-то писали, что проблем не видите ?

после реконнекта у вас стейты рассинхронизованы. На клиентах разное, в черновике другое, в чистовик (в messages) уже прилетело нечто третье.

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

PS/ кстати, по законам, черновики нельзя вот там вот просто взять и хранить на сервере :-) Чел набивая сообщение может впрямую оскорбить, послать, нарушить потом удалить и осознанно отправить корректное. Но черновик-то вы сохраните - и угадайте кто попал на статью ?

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)

Если DRAFT упала и там что-то было, а ты уже запостил, то потом внезапно клиенту восстанет из ада старый черновик. Возможно это чем-то хорошо, ну мол лучше данные сохранить, чем потерять, но всё равно странновато.

По-хорошему, при подъёме DRAFT она должна очищаться от мусора. То есть смотреть последние сообщения в MESSAGES с момента падения и удалять совпадающие. Если упала давно, просто чистить всё.

monk ★★★★★
()
Ответ на: комментарий от MKuznetsov

кстати, по законам, черновики нельзя вот там вот просто взять и хранить на сервере

А как же всякие онлайн-редакторы? В процессе редактирования в них всё летает туда-сюда по каналам провайдера и по закону Яровой обязательно к сохранению.

Или вот в mail.ru черновики при работе через браузер.

monk ★★★★★
()
Ответ на: комментарий от MKuznetsov

после реконнекта у вас стейты рассинхронизованы. На клиентах разное, в черновике другое, в чистовик (в messages) уже прилетело нечто третье.

  1. Если я пытался на двух-трёх клиентах одновременно что-то редактировать и оно уходило в черновик и при этом там попеременно везде часто рвались коннекты, то это и правда дурка. Тут гарантий излечения клиника не даёт.

  2. Про «в чистовик улетело третье». Тут не понял. Когда в чистовик что-то улетело, черновики сервер забывает. После реконнекта ты приходишь в чатик, а сервер тебе говорит «черновик пуст». И ты спокойно пишешь с чистого листа.

что вы будете делать с двумя клиентскими подключениями

Если открыто два устройства на одном чатике, то во втором в какие-то редкие моменты времени в поле ввода будет возникать или пропадать некий черновик, видимо. Сервер же знает все коннекты этого юзера до этого чатика, зашироковещает во всех них некие состояния черновика. Когда кто-то из них запостит - черновик умрёт везде.

PS/ кстати, по законам, черновики нельзя вот там вот просто взять и хранить на сервере :-) Чел набивая сообщение может впрямую оскорбить, послать, нарушить потом удалить и осознанно отправить корректное. Но черновик-то вы сохраните - и угадайте кто попал на статью ?

Это уже для юридического форума, а нам, технарям, на это глубоко насрать из ведра! Такие как мы атомные бомбы делают и потом тыщи японцев дохнет и ничего!

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от monk

А как же всякие онлайн-редакторы?

в броузерах есть вроде как свой storage и undo/redo изменения хранят там, у пользователя. Про это есть толстые книги и фреймворки

При закрытии страницы выплывает «сохранить черновик?» То есть запрашивают согласие пользователя для сохранения на серверах.

Если всё on-line сразу куда-то летит на сервер, то это:

- либо вариации SaaS (морда приклада просто прокинута. буквально по RDP/VNC),

- либо неприкрытый клавиатурный spy-ware, как ТС предлагает

- или как вариант - игруха/стрелялка

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от Obezyan
  1. Транзакции. Знаем такое слово. Но фича ради фичи не интересна, а высказывание «в отсутствии транзакций работать НОРМАЛЬНО ничего не может» ложно. Хорошо, что понятие нормальности у всех своё, бугага.

  2. Тред не про аттачи.

  3. Обычный подход в хайлоаде. Тяжело что-то джойнить без сетевого трафика на размазанной по трём дата-центрам базе.

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

  5. Лайки шардируются по (chat_id) например. Все лайки всех сообщений одного чата лежат на каком-то одном сервере. Не приходится ходить по всем дата-центрам. Не помню как точно выглядит это, но достать все лайки или их отсутствие на ряд извлечённых из MESSAGE сообщенек - это один запрос.

  6. Объект - это буквально как строка/тупл в PostgreSQL (или как JSON в MongoDB, но не JSON и не в MongoDB и если бы последовательность полей в JSON была фиксирована). Последовательность мессаг в чатике - тупо последовательность этих «документов» или «строк». В документе лежит штук 10-15 полей про эту мессагу. Про лайкании мессаги, если раньше на ней никаких реакций не стояло, мы этой месаге меняем одно поле без полной перезаписи объекта. А если были реакции, то ничего не меняем. Просто далее в базе LIKES уточняем чо какие реакции понаставлены. У «Message» есть только флаг «реакции какие-то есть». Если флаг тру, то пойти в LIKES для уточнения и достать оттуда.

На красоту архитектуры нам глубоко насрать, у нас цель микросекунды лутать. Если выглядит как говно, но едет быстро - мы за это душу отдаём. При этом конечно, возможны просёры данных, но мы их локализуем в «необязательных областях». Например лайк просрать можем себе позволить, а мессагу не можем. Ради полной суперсогласованности платить чем-то не готовы никогда, сорян, таковы законы микросекунд и большого бизнеса! Щепки рубят бабки летят! Такие дела.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 3)
Ответ на: комментарий от lesopilorama

то во втором в какие-то редкие моменты времени в поле ввода будет возникать или пропадать некий черновик, видимо.

это называется «нештатный канал передачи данных» :-) данные перелетают с одного устройства на другое. Можно вручить телефон третьему лицу и невозбранно ему что-то писать на компе в вашем сервисе, при этом следов не останется.

и это будет не ошибка реализации, это by-design.

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

это называется «нештатный канал передачи данных» :-) данные невозбранно перелетают с одного устройства на другое. Можно вручить телефон третьему лицу и невозбранно ему что-то писать на компе в вашем сервисе, при этом следов не останется.

и это будет не ошибка реализации, это by-design.

Ничем не отличается от «я купил второй телефон, поставил туда телегу, вошёл в неё и отдал другану». Вообще не вижу проблем, если ты так захотел.

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

На красоту архитектуры нам глубоко насрать, у нас цель микросекунды лутать.

Без качественной архитектуры микросекунды не залутать. Сам на одном из проектов (не мессенджер) бьюсь за выход из 16мс на «тяжелый» апи запрос, но там в основном TTFB битва уже.

Вы с таким подходом на полном скаку врежетесь в стену, чуть позже, вам просто пока за поворотом не видно о чем я пишу, всему свое время.

Obezyan
()
Ответ на: комментарий от Obezyan

Без качественной архитектуры микросекунды не залутать.

Очередное религиозно-категоричное утверждение.

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

Да не, я думаю нормально у нас продумано в части производительности и масштабируемости горизонтально, издавна закладывали такое. Но с просёром лайков, ага.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от lesopilorama

Очередное религиозно-категоричное утверждение.

Просто обязъянний опыт.

Ну если врежемся - переделаем, микроскопом гвозди поглужбе вобьём и норм.

Нет препятствий патриотам (с)

Надеюсь к тому времени удастся продать проект за миллиард яндексу с чистой совестью!

Это если у них архитектора не будет на этапе оценки, а если будет, то кек.

Obezyan
()
Ответ на: комментарий от lesopilorama

Ничем не отличается от «я купил второй телефон, поставил туда телегу, вошёл в неё и отдал другану»

отличается что набираемый текст будет передаваться сразу, без нажатия пользователем enter/send/save (это spy-ware) и не будет истории на серверах. И тем что эта функция побочная, она не нужна в основном функционале.

потенциально у вас на сервер попадёт то что юзер сознательно не посылал, и не должно туда попадать, храниться оно будет но без истории, так ещё и мультикаст по устройствам. Вы спроектировали ох@#ные ГРАБЛИ.

это всяким яндексам тов.майор выпишет предписание «привести в должный вид», а так как вы никто и зовут вас никак, да и контора скорее всего на бомжа, то закроют сразу.

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)