Групповой чат сложнее одиночного чата, почему он такой сложный?

Архитектура JavaScript

Групповой чат является основным требованием социального взаимодействия с несколькими людьми. Друг группы отправляет сообщение в группе, ожидая:

(1) онлайн группа друзейможет получить сообщение в первый раз;

(2) офлайн группа друзейМожет получать сообщения после входа в систему;

Доступность и сложность офлайн-сообщений групповых сообщений в режиме реального времени намного выше, чем у индивидуальных сообщений.

Каков общий процесс группового обмена сообщениями?

Существуют две основные структуры данных для группового бизнеса.

список участников группы:

t_group_users(group_id, user_id)

Голос за кадром: используется для описания количества участников в группе.

Групповая таблица офлайн-сообщений:

t_offine_msgs(user_id, group_id, sender_id,time, msg_id, msg_detail)

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

Примеры бизнес-сценариев:

(1) Предположим, что в группе 5 участников x, A, B, C и D, и член x отправляет сообщение;

(2) участники A и B находятся в сети и ожидают получать сообщения в режиме реального времени;

(3) участники C и D находятся в автономном режиме, ожидая получения сообщений в автономном режиме в будущем;


Типичный процесс доставки группового сообщения показан на рис. 1-4:

Шаг 1: Отправитель группового сообщения x отправляет групповое сообщение на сервер;

Шаг 2: сервер обращается к базе данных, чтобы узнать, сколько пользователей (x, A, B, C, D) входит в группу;

Шаг 3: Сервер обращается к кешу, чтобы запросить онлайн-статус этих пользователей;

Шаг 4: Для группыонлайнПользователи A и B, сервер групповых сообщений отправляет сообщения в режиме реального времени;

Шаг 5: Для группыне в сетиПользователи C и D из , групповой сервер сообщений для автономного хранения;


Типичный групповой процесс извлечения сообщений в автономном режиме показан на рис. 1-3.

Шаг 1: Средство извлечения сообщений из автономного режима C извлекает групповые автономные сообщения с сервера;

Шаг 2: сервер извлекает автономные сообщения из базы данных и возвращает пользователя группы C;

Шаг 3: Сервер удаляет групповые офлайн-сообщения пользователя группы C из базы данных;

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

Как оптимизировать и уменьшить избыточность сообщений?

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

таблица групповых сообщений:

t_group_msgs(group_id, sender_id, time,msg_id, msg_detail)

Голос за кадром: используется для хранения всего содержимого сообщения в группе.

Групповая таблица офлайн-сообщений, который необходимо оптимизировать:

t_offine_msgs(user_id, group_id, msg_id)

Голос за кадром: оптимизирован для хранения только msg_id.


После этой оптимизации были внесены некоторые изменения в групповую отправку онлайн-сообщений:

Шаг 3: Перед отправкой группового онлайн-сообщения каждый раз сохраните содержимое группового сообщения;

Шаг 6: Каждый раз, когда сохраняются автономные сообщения, для каждого пользователя сохраняется только msg_id вместо msg_detail;


Также была внесена модификация ответа при извлечении офлайн-сообщений:

Шаг 1: Сначала вытащите все автономные сообщения msg_id;

Шаг 3: Получить msg_detail в соответствии с msg_id;

Шаг 5: Удалите автономный msg_id;

** Оптимизирован процесс, чтобы обеспечить доступность сообщения о нем? **Например:

(1) Потеря сообщения может произойти при онлайн-доставке сообщений, например, при перезапуске сервера, потере пакетов маршрутизатора и сбое клиента;

(2) Извлечение офлайн-сообщений также может привести к потере сообщений по тем же причинам, что и выше;

Голос за кадром: Как и в случае с надежной доставкой сообщений один к одному, это достигается за счет добавления ACK на прикладном уровне Как насчет групповых сообщений?

Для групповых сообщений, как обеспечить надежную доставку сообщений через ACK прикладного уровня?


После оптимизации ACK прикладного уровня произошли некоторые изменения в групповой онлайн-отправке сообщений:

Шаг 3: После того, как сообщение msg_detail сохранено в таблице групповых сообщений, независимо от того, находится ли пользователь в сети или нет, msg_id сначала сохраняется в таблице сообщений в автономном режиме;

Шаг 6: После того, как онлайн-пользователи A и B получат групповое сообщение, им необходимо добавить ACK прикладного уровня, чтобы идентифицировать прибытие сообщения;

Шаг 7: Онлайн-пользователи A и B удаляют свое автономное сообщение msg_id после подтверждения прикладного уровня;


То же самое относится и к запросу, соответствующему групповому офлайн-сообщению:

Шаг 1: Сначала извлеките msg_id;

Шаг 3: Снова извлеките msg_detail;

Шаг 5: Окончательный ACK прикладного уровня;

Шаг 6: Сервер может удалить msg_id в таблице офлайн-сообщений только после получения ACK прикладного уровня;

Если сообщение получено, но нет времени на ACK прикладного уровня, получу ли я дубликаты сообщений?

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

Для каждого автономного сообщения, хотя сохраняется только msg_id, каждое автономное сообщение каждого пользователя сохраняет запись в базе данных,Есть ли способ уменьшить количество записей офлайн-сообщений?

Для группового пользователя в течение периода офлайн после выхода ta все групповые сообщения не должны быть получены.Нет необходимости вообще хранить оффлайн msg_id для каждого офлайн сообщения, а только последний тянуть к времени (или msg_id) автономного сообщения, при следующем входе в систему вы можете получить все групповые сообщения после этого, и нет необходимости хранить автономное сообщение msg_id, которое никто не вытащил.

список участников группы, добавьте атрибут:

t_group_users(group_id, user_id, last_ack_msg_id)

Голос за кадром: используется для описания количества участников в группе и msg_id (или времени) группового сообщения последнего подтверждения каждого участника.

таблица групповых сообщений,постоянный:

t_group_msgs(group_id, sender_id, time,msg_id, msg_detail)

Голос за кадром: он по-прежнему используется для хранения всего содержимого сообщения в группе.

Групповая таблица офлайн-сообщений:Больше не нужен.


После оптимизации таблицы офлайн-сообщений процесс доставки групповых онлайн-сообщений:

Шаг 3: После того, как сообщение msg_detail сохранено в таблице групповых сообщений, больше нет необходимости работать с таблицей офлайн-сообщений (перед оптимизацией необходимо вставить msg_id в таблицу оффлайн-сообщений);

Шаг 7: Онлайн-пользователи A и B могут обновить last_ack_msg_id после подтверждения прикладного уровня (перед оптимизацией msg_id необходимо удалить из таблицы офлайн-сообщений);


Процесс получения групповых офлайн-сообщений аналогичен:

Шаг 1. Получите автономные сообщения;

Шаг 3: автономное сообщение ACK;

Шаг 4: Обновите last_ack_msg_id;

Механизм ACK добавлен для обеспечения надежной доставки групповых сообщений.Предполагая, что в группе 500 пользователей, «каждое» групповое сообщение станет 500 ACK уровня приложения, что, по-видимому, оказывает огромное влияние на сервер.Есть ли способ уменьшить количество запросов ACK?

Массовое подтверждение — это распространенный способ уменьшить объем запросов.

Если каждое групповое сообщение получает ACK, это действительно окажет огромное влияние на сервер. Чтобы уменьшить количество запросов ACK, можно получить пакетный ACK. Существует два метода пакетного ACK:

(1) Каждый раз, когда N групповых сообщений подтверждаются, объем запроса уменьшается до 1/N от исходного;

(2) групповое сообщение ACK выполняется каждый временной интервал T, и может быть достигнут аналогичный эффект;

Массовые ACK потенциально могут вызвать новые проблемы: пользователи выходят из системы, если у них не было времени на групповые ACK-сообщения, поэтому следующий вход в систему кажетсяДублирующиеся офлайн-сообщения будут извлечены, что мне делать?

Клиент выполняет дедупликацию в соответствии с msg_id и не показывает его пользователю, чтобы обеспечить удобство работы.

В группе слишком много офлайн-сообщений, а получение происходит слишком медленно. Что делать?

Paging pull (вытягивание по запросу), подробности больше не раскрываются, это обычная схема оптимизации.

Суммировать

Новости группы все же очень интересны, подведем краткие итоги:

(1) Является ли это групповым онлайн-сообщением или групповым автономным сообщением, ACK прикладного уровня является гарантией достижимости;

(2) Сохраняется только одна копия группового сообщения, вместо сохранения автономного группового msg_id для каждого пользователя сохраняется только идентификатор группового сообщения/время последнего подтверждения;

(3) Чтобы уменьшить потоки сообщений, можно выполнять пакетные подтверждения;

(4) Если получено дублирующее сообщение, msg_id необходимо дедуплицировать, чтобы пользователь его не воспринимал;

(5) слишком много офлайн-сообщений, которые можно оптимизировать путем подтягивания страниц (вытягивания по требованию);

Идеи важнее выводов, я надеюсь, что у каждого есть что-то получить.

Architect's Road — делитесь техническими статьями, которые можно реализовать

Вы потеряли групповые сообщения?