Дизайн схемы MongoDB - чат реального времени
Я начинаю проект, который, я думаю, особенно подходит для MongoDB из-за скорости и масштабируемости, которые он предоставляет.
Модуль, в котором я сейчас заинтересован, - это общение с чатом реального времени. Если бы я сделал это в традиционной СУБД, я бы разделил ее на:
- Канал (канал имеет много пользователей)
- Пользователь (Пользователь имеет один канал, но много сообщений)
- Сообщение (сообщение имеет пользователя)
В целях использования этого случая я хотел бы предположить, что одновременно будет задействовано 5 каналов, каждый из которых обрабатывает не более 5 сообщений в секунду.
Конкретные запросы, которые должны быть быстрыми:
- Получить новые сообщения (на основе закладки, метки времени или счетчика)?
- Сообщение на канал
- Убедитесь, что пользователь может публиковать сообщения в канале
Принимая во внимание, что ограничение документа с помощью MongoDB составляет 4 МБ, как бы вы планировали схему? Как бы вы выглядели? Есть ли какие-либо ошибки, за которыми я должен следить?
Ответы
Ответ 1
Я использовал Redis, NGINX и PHP-FPM для моего проекта чата. Не супер элегантный, но он делает трюк. В головоломке есть несколько частей.
-
Существует очень простой PHP script, который получает клиентские команды и помещает их в один массивный список. Он также проверяет все СПИСОК ЗДАНИЙ и пользовательский СПИСОК пользователей, чтобы увидеть, есть ли сообщения, которые он должен доставить. Это проверяется клиентом, написанным в jQuery, и выполняется каждые несколько секунд.
-
Существует командная строка PHP script, которая управляет сервером в бесконечном цикле 20 раз в секунду, который проверяет этот список и затем обрабатывает эти команды. script обрабатывает то, что находится в комнате и разрешениях в памяти скриптов, эта информация не сохраняется в Redis.
-
Redis имеет СПИСОК для каждой комнаты и СПИСОК для каждого пользователя, который работает как приватная очередь. Он также имеет несколько счетчиков для каждой комнаты, в которой находится пользователь. Если счетчик пользователей меньше, чем общее количество сообщений в комнате, то оно получает разницу и отправляет его пользователю.
Я не смог подчеркнуть это решение, но, по крайней мере, из моего базового бенчмаркинга он мог бы обрабатывать тысячи сообщений в секунду. Существует также возможность переносить это на что-то вроде Node.js для повышения производительности. Redis также созревает и имеет некоторые интересные функции, такие как команды Pub/Subscribe, которые могут представлять интерес, которые могли бы, возможно, удалить опрос на стороне сервера.
Я искал решения на основе комет, но многие из них были сложными, плохо документированными или требовали, чтобы я изучал совершенно новый язык (например, Jetty- > Java, APE- > C) и т.д. Также доставка и переход Прокси могут иногда быть проблемой с кометами. Вот почему я застрял в опросе.
Я думаю, вы могли бы сделать что-то подобное с MongoDB. Коллекция для комнаты, коллекция для каждого пользователя, а затем коллекция, которая поддерживает счетчики. Вам все равно нужно написать фоновый демон или script, чтобы обрабатывать манипулирование, куда идут эти сообщения. Вы также можете использовать ограниченную коллекцию MongoDB, которая держит документы отсортированными, а также автоматически очищает старые сообщения, но это может быть затруднено в поддержании правильных счетчиков.
Ответ 2
Зачем использовать mongo для системы обмена сообщениями? Независимо от того, насколько быстро статический магазин (и монго очень быстрый), будь то mongo или db, чтобы имитировать очередь сообщений, вам придется использовать какой-то опрос, который не очень масштабируемый или эффективный. Конечно, вы не делаете ничего ужасного, но почему бы вам не использовать правильный инструмент для правильной работы? Используйте систему обмена сообщениями, например Rabbit или ActiveMQ.
Если вы должны использовать mongo (возможно, вы просто хотите поиграть с ним, и этот проект - хороший шанс сделать это?) Я полагаю, у вас будет коллекция для пользователей (где каждый пользовательский объект имеет список очереди, которые пользователь слушает). Для сообщений у вас может быть коллекция для каждой очереди, но тогда вам придется опросить каждую интересующую вас очередь для сообщений. Лучше было бы иметь одну коллекцию в качестве очереди, так как легко в mongo делать "in" запросы в одной коллекции, поэтому было бы легко сделать такие вещи, как "получить все сообщения, более новые, чем X, в любых очередях, где очередь .name в списке [a, b, c]".
Вы также можете подумать о том, чтобы настроить свою коллекцию как коллекцию с ограниченным монгом, что означает, что вы говорите манго, когда вы настраиваете коллекцию, в которой ваша коллекция должна содержать только Х количество байтов или X количество элементов. Добавление дополнительных элементов имеет поведение First-In, First-Out, которое идеально подходит для очереди сообщений. Но опять же, это не действительно система обмена сообщениями.
Ответ 3
1) ape-project.org
2) http://code.google.com/p/redis/
3) после того, как вы пройдете все это - вы можете глупыми данными в mongodb для ведения журнала и хранения согласованных данных (пользователей, каналов), а также