Схема базы данных для проекта живого чата с комнатами - PullRequest
2 голосов
/ 30 декабря 2011

Для моего университетского проекта я разрабатываю веб-сайт динамического чата с комнатами, регистрацией пользователей и т. Д. Я спланировал всю систему без одного аспекта.Комнаты.Я запутался в том, как спроектировать базу данных для комнат.

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

Первоначально я собирался создать таблицу в своей базе данных с именем messages и иметь такие поля, как это:

| r_id | u_id | message | timestamp |

r_id и u_id будут внешними ключами для идентификатора комнаты и идентификатора пользователя соответственно.Выполнение этого означает, что мне нужно будет вставлять новую запись всякий раз, когда пользователь отправляет сообщение, и периодически запускать оператор SELECT для каждого клиента (скажем, каждые 3 секунды или около того), чтобы получать последние сообщения.Я беспокоюсь об этом из-за того, что таблица будет огромной, выполнение этих операторов может привести к большим накладным расходам и занять много времени.

Другой способ, которым я думал о реализации этого, - создать новую таблицу базы данных длякаждая комнатаСкажем, пользователь создает 3 комнаты с именами General, Programming и Gaming, таблицы базы данных будут выглядеть так: room_general, room_programming, room_gaming, каждая с полями, такими как:

| u_id | message | timestamp |

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

Итак, я застрял на том, что лучшесделать этоЕсли что-то изменится, то я буду использовать технологию MySQL с PHP и целую лототу AJAX.

Спасибо за любую помощь!

Ответы [ 5 ]

2 голосов
/ 30 декабря 2011

Это плохая идея создать стол на комнату. Трудно реализовать и трудно поддерживать.

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

SELECT * FROM messages WHERE r_id=X ORDER BY timestamp DESC LIMIT X,Y

Просто убедитесь, что ваш (r_id, timestamp) проиндексирован вместе в этом порядке, чтобы сделать этот выбор с помощью индекса:

ALTER TABLE `messages` ADD KEY `IN_messages_room_time` (`r_id`, `timestamp`);

Если у вас все еще будут проблемы с производительностью (вероятно, у вас не будет), просто добавьте кэш памяти на 1-3 секунды (используя memcache) и извлекайте сообщения из БД один раз в 1-3 секунды.

Также посмотрите на ответ Аполлона Кларка: https://stackoverflow.com/a/8673165/436932, чтобы предотвратить сохранение огромного количества ненужных старых сообщений: вы можете просто поместить его в таблицу MYISAM archive или просто удалить.

1 голос
/ 30 декабря 2011

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

Используя таблицу транзакций, вот как она будет передаваться:

  1. пользователь входит в чат
  2. пользователь вводит сообщение, которое сохраняется в таблице транзакций.
  3. каждые 500 мс или 3 с, каждый пользователь в комнате будет запрашивать таблицу транзакций, чтобы получить последние обновления за последние 500 мс или 3 с

    .
    SELECT * FROM message_transactions WHERE timestamp > 123456789
    
  4. задание CRON выполняется каждые 5 минут или 1 час и удаляет все записи старше 5 минут или сколь угодно долго, как вы хотите, чтобы история была.

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

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

С другой стороны, вы можете просто получить библиотеку PHP to IRC и назвать ее днем. Кроме того, если вам интересно узнать, как Facebook реализует свою систему чата на основе AJAX.

1 голос
/ 30 декабря 2011

Чтобы ускорить вашу базу данных, взгляните на индексирование ваших таблиц: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

В вашем случае я предполагаю, что вы ВЫБИРАЕТЕ сообщения по r_id при выполнении JOIN для пользовательской таблицы через u_id. Я бы проиндексировал столбцы r_id и u_id. Я ни в коем случае не эксперт в этом вопросе, потому что я сделал только то, что работает для моих собственных проектов. Я не понимаю все за и против индексации, только то, что индексация тех столбцов, которые обычно используются в качестве индексов, ускоряет процесс. Google "учебник по индексу mysql", вы найдете гораздо больше информации.

Не сходите с ума и не индексируйте каждый столбец, вы замедляете свои ВСТАВКИ и ОБНОВЛЕНИЯ.

Я также предлагаю очищать журналы чата каждые несколько дней / недель или перемещать их на другой сервер для архивных целей, если это то, что вы хотите / должны сделать.

0 голосов
/ 21 апреля 2014

Что вы можете сделать, это:

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

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

0 голосов
/ 30 декабря 2011

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

Использование memcached в качестве буфера базы данных для сообщений чата

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