Как хранить чат в базе данных
Перейти к содержимому

Как хранить чат в базе данных

  • автор:

Система личных сообщений

Подскажите, пожалуйста, как устроена система личных сообщений между пользователями в крупных проектах (Вконтакте, Одноклассники, Topface и т.п) с учетом масштабирования? Интересует именно хранение данных о пользователях/чатах/сообщениях и доступ к этим данным.

Допустим у нас есть 100 000 000 пользователей и необходимо сделать горизонтальное масштабирование (шардинг) этих данных на 200 MySQL серверов. На данный момент, я вижу это следующим образом: разделяем всех пользователей и данные на 200 серверов по user_id, получается примерно 500 000 юзеров на каждый сервер. Можно еще разделить данные на споты по 1000 юзеров и получится, что на каждом сервере БД будет 500 спотов по 1000 юзеров (всего 500 000 юзеров на сервер).

Доступ к серверам БД/спотам можно вычислять по user_id, например spot_id = user_id % 1000. Каждый спот будет хранить данные в виде таблиц, например:

Spot1: — spot1_users (информация о пользователях) — spot1_chats (информация о чатах между пользователями) — spot1_messages (сообщения из чатов) .

Spot2: — spot2_users — spot2_chats — spot2_messages . Проблема возникает тогда, когда необходимо хранить/получать общие данные между юзерами. Например, 2 пользователя начинают переписку между собой. В этом случае необходимо создать чат в таблице spotN_chats и поместить туда информацию chat_id (id чата), receiver_id(id получателя), sender_id (id отправителя). Сообщения будут хранится в таблице messages (chat_id, message, time).

Теперь начинается самое интересное — пользователи начинают переписку между собой. Здесь необходимо сделать такие базовые операции: 1) Создание нового чата между 2 пользователями 2) Получение информации о чате или списке чатов конкретного пользователя 3) Создание нового сообщения 4) Получение списка сообщений по chat_id

Также есть 2 варианта развития событий: 1) пользователи находятся на одном споте (например, spot1); 2) пользователи находятся на разных спотах (например, spot1 и spot2);

Задача 1. Пользователь1 решил начать переписку с пользователем2. В этом случае необходимо создать новый чат в БД. Если пользователи на одном споте, то можно просто создать новый чат в таблице spot1_chats, получать chat_id, а дальше создавать новые сообщения в таблице spot1_messages с полученным chat_id. Но если пользователи находятся на разных спотах (spot1, spot2), то такой подход не будет работать, поскольку чтобы каждый пользователь увидел список своих чатов, то их нужно дублировать на 2 споты одновременно. Но в таком случае chat_id будут разными для 2 таблиц(spot1_chats, spot2_chats) если использовать поле autoincrement для chat или же нужно строить какой-нибудь общий для 100 млн. пользователей генератор id для новых чатов. Кроме того, если 2 пользователи на одном споте, то при дублировании чатов все равно будет создан только 1 чат в таблице spot1_users, а вот если мы решим перенести 1 пользователя на другой спот, то как дублировать информацию о чатах?

Задача 2. Пользователь1 отправляет сообщение пользователю2, chat_id у нас уже есть после создания нового чата. Здесь возникает та же самая проблема, что и в первой задаче. Если 2 пользователи на одном споте, то мы просто добавляем новое сообщение в таблицу spot1_messages, но если в будущем захотим перенести пользователя на другой спот, то как дублировать сообщения? Если же пользователи на разных спотах, то для отправки сообщения необходимо создать новое сообщение в таблице spot1_messages и в таблице spot2_messages. Кроме того, если мы хотим обновлять какой-нибудь счетчик новых сообщений или время последнего сообщения в чатах, то нужно будет также обновлять информацию о чатах в таблицах spot1_chats и spot2_chats. Получается для простой отправки одного сообщения необходимо будет сделать несколько запросов в БД, а именно: создать новое сообщения в таблицах spot1_messages и spot2_messages, а также обновить информацию о чате в таблицах spot1_chats и spot2_chats.

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

Хранение сообщений для чатов

добрый день
у меня возник такой вопрос » как хранить и быстро отдавать сообщения из чата»
изначально была идея хранить все в реляционной базе данных, но тут возникает такая проблема, что с некоторым временем таблица сообщений разрастется, и скорость отдачи замедлиться
была идея репликации по юзерам(стоит ли такое делать)
еще был вариант «перебрасывать пачками» из реляционной в не реляционную(например монгу), но тут возникает вопрос получения сообщений с пагинацией
что посоветуете опираясь на свой опыт ?
заранее спасибо

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Хранение сообщений в базе данных
Здравствуйте! Подскажите пожалуйста чайнику, как лучше сделать: Будет сайт (что-то типа соц.сети).

Как лучше сделать хранение сообщений в БД?
Чисто теоретический вопрос, как лучше сделать хранение сообщений в БД, например, для форума, такого.

есть ли бесплатные хостинги для ICQ чатов
привет всем, есть ли в наше время бесплатный хостинг для ICQ ЧАТОВ

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

1635 / 1136 / 171
Регистрация: 23.07.2010
Сообщений: 6,730
для начала (это если говорить по реляционные) прочитать про индексы
43 / 43 / 23
Регистрация: 20.11.2017
Сообщений: 80

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

267 / 231 / 78
Регистрация: 16.12.2015
Сообщений: 943
Записей в блоге: 4

Shchusia, вот чего точно не стоит делать — это городить мосты между реляционными и не реляционными БД. Это тут явно лишнее.
Как вариант, стоит сразу оценить масштабы задачи. Как минимум, кол-во пользователей, которое будет нагружать систему. Если останавливаться на варианте РСУБД, то надо ознакомиться с индексами, партиционированием таблиц и, возможно, денормализацией данных (в пользу скорости работы).
Как вариант, возможно использовать что-то документоориентированное couchdb, cassandra. Может быть Redis с его publish/subscribe.

Проектирование архитектуры базы данных для чата

Проектирование архитектуры базы данных для чата

Как вообще, должен работать чат. У вас есть пользователи, которые могут общаться в чате. Чат может состоять из нескольких групп (таблица chat), по сути, из отдельных чатов в каждом из которых могут общаться пользователи (таблица party). Сообщения каждого чата добавляются (таблица messages) от участников чата, которым можно показывать уведомления о добавлении новых сообщений и проверять, какие сообщения пользователь уже прочитал (таблица message_status).

Полагаю, что у вас уже есть таблица users, в которой хранятся пользователи.

Таблица со списком групп чата

В таблице со списком групп чата будут храниться данные группах чата. Таблица выглядит следующим образом:

Название таблицы — chat

Наименование Описание
chat_id порядковый id чата
name заголовок чата, его название
user_id id пользователя создавшего чат

Таблица со списком участников чата

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

Название таблицы — party

Наименование Описание
chat_id id группы чата
user_id id пользователя, который учавствует в переписке чата

Таблица со списком сообщений

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

Название таблицы — messages

Наименование Описание
message_id порядковый id сообщения
chat_id id чата
user_id id пользователя, который добавил сообщение
contect содержимое сообщения
date_create дата добавления сообщения

Таблица со статусами сообщений

В таблице со статусами сообщений будут храниться статусы уведомлений, определяющих просмотрел ли определенный пользователь новое добавленное сообщение. Таблица выглядит следующим образом:

Название таблицы — message_status

Наименование Описание
message_id id сообщения
user_id id пользователя
is_read прочитано ли сообщение

Доводилось ли вам создавать чат для своего сайта? Если да, то какая архитектура в нем используется?

Структура хранения сообщений чата в базе данных [закрыт]

Закрыт. На этот вопрос невозможно дать объективный ответ. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах.

Закрыт 7 лет назад .

Собственно, вопрос навеян другим вопросом. Заключается в следующем. Какой оптимальный способ хранения сообщений чата? Может быть лучше их сохранять вообще просто в файл (ведь обращение к старым практически исключено, а вычитка последних может идти и из оперативной памяти)? Или может быть лучше (как в упомянутом вопросе) рассматривать хранение сообщений в базе в виде JSON-строк за определенный период времени? А может все-таки лучше их хранить в базе в виде «одно сообщение — одна строка» и при этом все данные расположены по полям? Какие еще есть варианты? Какие у этих вариантов (и других) плюсы и минусы?

Отслеживать
задан 25 июл 2016 в 20:38
user212277 user212277
Если вам дан исчерпывающий ответ, отметьте его как верный (галочка напротив выбранного ответа)
25 июл 2016 в 21:34

@Mihanik71 Несомненно, так и поступлю. Но не ранее, чем отвечающие начнут читать вопрос и отвечать по существу вопроса.

– user212277
26 июл 2016 в 8:06

Укажите какими средствами делается серверная часть. И какую БД вы имеете ввиду. Если реляционную — отдельная строка на сообщение, без вариантов. Если документарную или около того — то видимо JSON или как там она документ хранит. С файлами — в определенных случаях можно сделать оптимально, но объем работы на пару порядков выше.

26 июл 2016 в 8:21

@Mike Прочитайте вопрос. Ведь черным по белому написано: как лучше хранить сообщения чата? Может лучше вообще без базы? Причем здесь Ваши комментарии по поводу базы данных? Причем здесь непосредственно JSON, если я в вопросе написал, что это как вариант, а как другой вариант — традиционное сохранение в базе по строкам и полям. Какая разница при этом какими средствами делается серверная часть? Есть средства, которые позволят ее сделать, но не позволят использовать базу данных или файловую систему?

– user212277
26 июл 2016 в 8:28

Очень хотелось бы уточнить у тех, кто требует правки, как можно отредактировать простой вопрос:Какой оптимальный способ хранения сообщений чата?И да.Ну очень много ответов может быть основано сугубо на чьем-то мнении. Вот их бы и хотелось услышать. Но услышать мнения по существу вопроса, а не ответы о том, как данные из базы будут потом плохо читаться.В вопросе указано, что это чат (не мессенджер) и читаться сообщения не будут.Ответов по существу нет, несмотря на разжеванный вопрос?Как, уважаемые, господа-товарищи вы предлагаете его переформулировать?Может прочтете его внимательно для начала?

– user212277
26 июл 2016 в 8:55

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Хранение в JSON данных за день/месяц/год:

+Легко отдавать данные за период

-Отсутствует возможность поиска

-Увеличение размера хранимых данных

-Большой объём передаваемых данных

-Усложнение системы хранения данных (сначала нужно хранить где то данные за период, потом переносить в базу)

Хранение в файлах данных за день/месяц/год:

+Легко отдавать данные за период

-Отсутствует возможность поиска

-Увеличение размера хранимых данных

-Большой объём передаваемых данных

-Усложнение системы хранения данных (сначала нужно хранить где то данные за период, потом переносить в файл)

Хранение в базе:

+Легко отдавать данные за период

+Стандартные возможность поиска

+Передаём только нужные данные

-Хранятся актуальные и старые сообщения

В лучшую сторону ничего не изменится если Вы будете хранить сообщения в JSON.

  • Места занимает столько же, а то и больше.
  • Теряется возможность запросов. Нельзя будет сделать сложных запросов.
  • Передавать данные сложнее. (Кто то очень активный наобщается на 10 метров и будете Вы на клиент их передавать).

Хранить в файлах историю по дням можно, но тоже не особо что то поменяет.

Вы боитесь что если у Вас будет несколько миллионов записей, то у Вас скорость запросов упадёт при обычном селекте? Это не так доступ же линейный.

А по всему остальному в чём разница — хранить в базе или в файлах? Что то что то место занимает.

Лучше чем просто в базе ещё вроде не придумали.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *