MongoDB架构设计 - 实时聊天

时间:2010-05-29 21:02:39

标签: mongodb rabbitmq activemq schema-design nosql

由于它提供的速度和可扩展性,我正在启动一个我认为特别适合MongoDB的项目。

我目前感兴趣的模块是与实时聊天。如果我要在传统的RDBMS中执行此操作,我会将其拆分为:

  • 频道(频道有很多用户)
  • 用户(用户有一个频道,但有很多消息)
  • 消息(消息有用户)

这个用例的目的,我想假设一次通常有5个通道处于活动状态,每个通道每秒最多处理5个消息。

需要快速的特定查询:

  • 获取新消息(基于书签,时间戳或者递增计数器?)
  • 向频道发布消息
  • 验证用户是否可以在频道中发帖

请记住,MongoDB的文档限制是4mb,您将如何设计架构?你会是什么样的?有什么问题需要注意吗?

3 个答案:

答案 0 :(得分:3)

为什么要将mongo用于邮件系统?无论静态存储有多快(并且mongo非常快),无论是mongo还是db,模仿消息队列都必须使用某种轮询,这种轮询不是很可扩展或高效。当然,你没有做任何非常激烈的事情,但为什么不只是使用合适的工具来做正确的工作呢?使用RabbitActiveMQ等邮件系统。

如果你必须使用mongo(也许你只是想玩它并且这个项目是一个很好的机会吗?)我想你会有一个用户集合(其中每个用户对象都有一个列表用户侦听的队列)。对于消息,您可以为每个队列设置一个集合,但是您必须轮询您对消息感兴趣的每个队列。更好的方法是将一个集合作为一个队列,因为mongo很容易在一个集合上进行“in”查询,因此很容易做到这样的事情:“在队列的任何队列中获取比X更新的所有消息列表中的.name [a,b,c]“。

您也可以考虑将您的集合设置为mongo capped集合,这意味着您在设置集合时告诉mongo,您的集合应该只保存X个字节或X个项目。添加其他项目具有First-In,First-Out行为,这对于消息队列来说非常理想。但同样,它并不是真正的消息传递系统。

答案 1 :(得分:3)

我使用了Redis,NGINX&我的聊天项目的PHP-FPM。不是超级优雅,但它确实有把戏。这个难题有几个部分。

  1. 有一个非常简单的PHP脚本接收客户端命令并将它们放在一个大型LIST中。它还会检查所有房间LIST和用户私有LIST,以查看是否有必须提供的消息。这是由jQuery& amp;它每隔几秒就完成一次。

  2. 有一个命令行PHP脚本,它在无限循环中运行服务器端,每秒20次,检查此列表然后处理这些命令。该脚本处理脚本内存中的空间和权限,此信息不存储在Redis中。

  3. Redis每个房间都有一个列表。每个用户的LIST,作为私人队列运行。它还为用户所在的每个房间设置了多个计数器。如果用户计数器小于房间中的总消息数,则它会得到差异并将其发送给用户。

  4. 我无法对此解决方案进行压力测试,但至少从我的基本基准测试中,它可能每秒处理数千条消息。还有机会将此端口移植到Node.js以提高性能。 Redis也在成熟,并且有一些有趣的功能,如Pub / Subscribe命令,可能会引起人们的兴趣,可能会删除服务器端的轮询。

    我研究了基于Comet的解决方案,但其中许多都很复杂,文档记录很差或需要我学习一种全新的语言(例如Jetty-> Java,APE-> C)等等。另外交付和通过代理有时可能是Comet的问题。所以这就是我坚持投票的原因。

    我想你可以用MongoDB做类似的事情。每间客房的收藏品,每位用户的收藏品和然后是一个维护柜台的集合。您仍然需要编写后端守护程序或脚本来处理这些消息所在的位置。你也可以使用MongoDB的“有限集合”,它可以保存文件的排序和安排。还会自动清除旧消息,但在维护正确的计数器时可能会很复杂。

答案 2 :(得分:1)

1)ape-project.org

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

3)在完成所有这些之后 - 你可以将数据变成mongodb用于记录和存储一致的数据(用户,频道)