Дизайн схемы MongoDB-чат в реальном времени

Я начинаю проект, который, я думаю, будет особенно подходит для MongoDB из-за скорости и масштабируемости, которые он предоставляет.

модуль, который меня сейчас интересует, - это чат в реальном времени. Если бы я должен был сделать это в традиционной РСУБД, я бы разделил его на:

  • канал (канал имеет много пользователей)
  • User (пользователь имеет один канал, но много сообщений)
  • сообщение (сообщение имеет пользователя)

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

конкретные запросы, которые должны быть быстро:

  • Fetch новые сообщения (на основе закладки, отметки времени, может быть, или приращение счетчика?)
  • Отправить сообщение на канал
  • убедитесь, что пользователь может размещать в канале

имея в виду, что ограничение документа с MongoDB - 4mb, как бы вы стали разрабатывать схему? Как бы выглядела твоя? Есть ли какие-нибудь gotchas я должен следить за?

3 ответов


Я Redis, NGINX & PHP-FPM для моего проекта чата. Не очень элегантно, но делает свое дело. Есть несколько частей головоломки.

  1. существует очень простой PHP скрипт, который получает клиентские команды и помещает их в один массивный список. Он также проверяет все списки номеров и приватный список пользователей, чтобы узнать, есть ли сообщения, которые он должен доставить. Это опрашивается клиентом, написанным в jQuery, и это делается каждые несколько считанные секунды.

  2. существует PHP-скрипт командной строки, который работает на стороне сервера в бесконечном цикле, 20 раз в секунду, который проверяет этот список, а затем обрабатывает эти команды. Скрипт обрабатывает, кто в какой комнате и разрешения в памяти скриптов, эта информация не хранится в Redis.

  3. Redis имеет список для каждой комнаты и список для каждого пользователя, который работает как частная очередь. Он также имеет несколько счетчиков для каждой комнаты, в которой находится пользователь. Если счетчик пользователей меньше общего количества сообщений в комнате, затем он получает разницу и отправляет ее пользователю.

Я не смог стресс-тестировать это решение, но, по крайней мере, из моего базового бенчмаркинга он, вероятно, может обрабатывать многие тысячи сообщений в секунду. Существует также возможность перенести это на что-то вроде узла.js для повышения производительности. Redis также созревает и имеет некоторые интересные функции, такие как команды Pub/Subscribe, которые может быть интересно,что, возможно, удалит опрос на стороне сервера.

Я просмотрел решения на основе Comet, но многие из них были сложными, плохо документированными или потребовали бы от меня изучения совершенно нового языка(например, Jetty->Java,APE->C) и т. д... Также доставка и прохождение через прокси иногда могут быть проблемой с Comet. Так вот почему я застрял с опросом.

Я думаю, вы могли бы сделать что-то подобное с MongoDB. Собрание в комнату, a коллекция для каждого пользователя , а затем коллекция, которая поддерживает счетчики. Вам все равно нужно написать фоновый демон или скрипт для обработки manging, куда идут эти сообщения. Вы также можете использовать "ограниченные коллекции" MongoDB, которые сортируют документы и автоматически очищают старые сообщения, но это может быть сложно в поддержании правильных счетчиков.


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

Если вы должны использовать mongo (возможно, вы просто хотите поиграйте с ним и этот проект-хороший шанс сделать это?) Я предполагаю, что у вас будет коллекция для пользователей (где каждый объект пользователя имеет список очередей, которые пользователь слушает). Для сообщений вы можете иметь коллекцию для каждой очереди, но тогда вам придется опрашивать каждую интересующую вас очередь для сообщений. Лучше было бы иметь одну коллекцию в качестве очереди, так как в mongo легко делать" в "запросы на одну коллекцию, поэтому было бы легко делать такие вещи, как" получить все сообщения новее чем X в любых очередях, где очередь.имя в списке [a, b, c]".

вы также можете рассмотреть возможность настройки вашей коллекции как коллекции с шапкой монго, что просто означает, что вы говорите монго при настройке коллекции, что ваша коллекция должна содержать только X количество байтов или X количество элементов. Добавление дополнительных элементов имеет поведение First-In, First-Out, которое в значительной степени идеально подходит для очереди сообщений. Но опять же, это не система обмена сообщениями.


1) ape-project.org

2) http://code.google.com/p/redis/

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