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

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

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

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

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

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

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

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


person Nick    schedule 29.05.2010    source источник


Ответы (3)


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

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

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

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

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

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

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

person Klinky    schedule 30.05.2010

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

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

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

person Steve B.    schedule 29.05.2010
comment
Я бы не стал утверждать, что существующие решения MQ действительно намного лучше, чем некоторые из существующих решений NoSQL. Многие технологии MQ кажутся сложными и изощренными, плюс производительность не всегда так хороша, стабильность и портативность также могут быть принесены в жертву. См .: bhavin.directi.com/rabbitmq-vs-apache -activemq-vs-apache-qpid - person Klinky; 30.05.2010
comment
Существуют достойные решения MQ, я просто нахожу, что они не имеют особых функций, ZeroMQ и Kestrel оба хороши для своих целей. ActiveMQ, с другой стороны, ужасен. - person Michael; 30.05.2010
comment
@Klinky Я уверен, что почти любое конкретное решение MQ (особенно ActiveMQ) будет справляться с проблемой обмена сообщениями (EDA) в разы лучше, чем пользовательское решение, основанное на NoSQL неопределенного типа (вы имели в виду базу данных, ориентированную на документы, или ключ- хранилище значений или что?), потому что решения MQ разработаны для этой проблемы, а FTN ActiveMQ использует собственное оптимизированное высокопроизводительное хранилище данных для сохранения очереди. - person Vasil Remeniuk; 03.06.2010
comment
@Steve B. ..., который не очень масштабируем или эффективен - не согласен с масштабируемостью (хотя согласен с эффективностью и производительностью). Почему? В отличие от хранения очередей в памяти (что приводит к проблемам, если у вас есть 1+ узел в вашем кластере - вам нужно либо настроить репликацию, либо построить сеть брокеров), заставить несколько потребителей работать с постоянной очередью кажется менее проблематичным (особенно с учетом сценариев отказов). - person Vasil Remeniuk; 03.06.2010
comment
@Vasil. Кажется, что все решения MQ имеют свой собственный мыслительный процесс и методологию с большими объемами спецификаций и скучной документацией. Многие из них подходят для корпоративных ситуаций, которые могут нуждаться в сложной настройке. Когда я исследовал MQ, я нашел блог о сложностях получения стабильной версии для корпоративного SMS-приложения, прочитал о Twitter, разрабатывающем собственное решение MQ из-за сбоя с ActiveMQ и RabbitMQ. Также опубликованная мною ссылка предлагает ActiveMQ с 22K msg / sec, что не является демоном скорости. Об их настройке дается не так много подробностей, но это, по крайней мере, одна точка данных. - person Klinky; 04.06.2010
comment
@Klinky Разработчики Twitter сделали много странных вещей, вы знаете :) (если у вас была возможность прочитать книгу о Scala одного из ведущих архитекторов Twitter, вы можете догадаться, насколько хорошо их решение MQ). Что касается ActiveMQ - лично у меня был очень хороший опыт работы с ним (я использовал его для создания просто огромной распределенной системы массовой рассылки). Пропускная способность ~ 30-60 к / с - это базовая настройка с одним брокером - если вы построите сеть брокеров, производительность может быть в разы выше. - person Vasil Remeniuk; 04.06.2010
comment
@Vasil, каждому свое, наверное. Я только что счел NoSQL более простым для начала. Я понимаю, что такое очередь, и что я хочу ставить в нее что-то и снимать. Что-то вроде Redis позволяет сделать это очень легко. Что касается производительности Redis, я могу помещать в очередь около 35 КБ сообщений / сек. Потенциально получить из очереди со скоростью до 400 КБ сообщений / сек. Протестировано на моем Celeron E3200 1 МБ L2 при разгоне 3,8 ГГц, внутри Ubuntu Virtualbox с включенным IntelVT. Redis не является многопоточным, поэтому он использует только одно из двух ядер. Я полагаю, это зависит от того, что вам нужно от вашего «MQ». - person Klinky; 05.06.2010
comment
››› Я могу поставить в очередь около 35 000 сообщений в секунду. Потенциально получить из очереди со скоростью до 400 КБ сообщений / сек. У меня не было много шансов запачкать руки с Redis, и я был бы счастлив взглянуть на хорошую архитектуру, которая его использует - ваше решение MQ является частью проприетарной системы или оно открыто? - person Vasil Remeniuk; 05.06.2010

1) ape-project.org

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

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

person Toby    schedule 14.06.2010