在使用消息队列实现的聊天系统中获得持久性

时间:2015-02-26 21:52:37

标签: architecture erlang message-queue

我和我的团队在Erlang中使用称为Fubar的消息队列实现了一个基本的聊天系统。该系统的主要要求之一是能够检索聊天记录,因此需要将其保留在该行的某个位置。

所以问题是这样的:在一般意义上,你将如何挂钩到这个系统,以便将聊天消息存储在数据库中以便日后检索?

一种解决方案是使用某种聊天记录程序进程订阅所有聊天记录并只存储所有消息。这将是一个非常敏感的地方,一个单一的失败点 - 所以建筑方面可能不是最好的主意。

另一个解决方案是在消息队列服务器和客户端之间使用某种代理,这些客户端在消息通过时抓取消息。

我们有兴趣听听您的想法!

1 个答案:

答案 0 :(得分:3)

历史数据库至少是单点故障,除非您遇到多主复制的麻烦,这是它自己的小任务。除非您每秒管理数百万条消息,否则您应该可以使用记录进程来订阅聊天并将其推送到数据库。

但是如果你会有数百万条消息,并且你已经设置了一个记录过程订阅所有聊天怎么办?也就是说,至少不是一个有利的情况。另一个不利的因素是,单个数据库表中会有大量的聊天消息,没有任何分区方案。显然,问题的某些划分是有序的。

我可能会改为每个通道有一个日志记录进程,并且在数据库端也有每个通道的数据库分区 - 因此每个通道的检索速度很快,但您仍然可以编写按日期检索的查询或用户全球。根据数据库的设置方式,您可以按日期对数据库进行进一步分区(这会限制新写入索引的成本),如果由于加载而需要多个数据库主数据,您现在可以通过以下方式对主数据进行干净分区。频道也是(或者使用三个或更多,例如:一个作为注册/用户数据的外部母版,另一个作为频道AM的外部母版,第三个作为新西兰频道的外国母版或其他)。

考虑到这一点,如果您的数据本身并不是关系型的,那么完全可以将Erlang保留在Erlang中以满足数据库要求,并使用Mnesia或ETS / DETS来持久存储消息。聊天数据没有任何固有的关系,所以这可能是他们所有人最顺利的解决方案。如果你确实在聊天系统外部有一个真正的关系后端(也许聊天只是你提供的服务的一个方面),最好在大型系统中保留这些内容,将聊天记录放在Mnesia / ETS / DETS中并编写一个强制检查,将聊天系统用户数据与规范关系数据库同步。

在任何情况下,真正的问题是分区,每个通道一个记录器和一个数据库分区(至少,每个通道每月一个分区更可能)为您提供了一个很好的起点,可以将分区聚合成块能够以理智的方式进行管理。还要注意,代码和数据中的这种分区允许您将问题分散到硬件和erlang节点之间,因此任何一个地方的崩溃只会中断任何通道和日志记录在那里运行 - 让其他节点可用于复活快速影响通道,并在以后同步数据分区而不会遇到主要负责人#34;一些问题(但是,你仍然需要编写代码才能编写代码)。