MongoDB Schema Design - чат в реальном времени - PullRequest
14 голосов
/ 30 мая 2010

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

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

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

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

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

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

Учитывая, что лимит документов с MongoDB составляет 4 МБ, как бы вы пошли на разработку схемы? Как бы выглядел ваш? Есть ли какие-нибудь ошибки, за которыми мне следует следить?

Ответы [ 3 ]

3 голосов
/ 30 мая 2010

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

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

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

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

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

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

Я полагаю, вы могли бы сделать нечто подобное с MongoDB. Коллекция на комнату, коллекция на пользователя и затем коллекция, которая поддерживает счетчики. Вам все еще нужно написать внутренний демон или сценарий, чтобы обрабатывать, куда направляются эти сообщения. Вы также можете использовать «ограниченные коллекции» MongoDB, которые сохраняют документы отсортированными, а также автоматически удаляют старые сообщения, но это может усложнить поддержание правильных счетчиков.

3 голосов
/ 30 мая 2010

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

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

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

1 голос
/ 14 июня 2010

1) ape-project.org

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

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

...