【问题标题】:Getting persistence in a chat system implemented with message queues在使用消息队列实现的聊天系统中获得持久性
【发布时间】:2015-04-29 11:31:09
【问题描述】:

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

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

一种解决方案是使用某种聊天记录程序来订阅所有聊天并仅存储所有消息。这将是一个非常敏感的地方,一个单点故障——所以从架构角度来说可能不是最好的主意。

另一种解决方案是在消息队列服务器和客户端之间设置某种代理,以便在消息通过时将它们收集起来。

我们很想听听您的想法!

【问题讨论】:

  • 不幸的是,执行此操作的技术种类繁多,并且在不了解有关系统的任何具体信息的情况下,我只能给出一般的“这种方式,那种方式或另一种方式——这取决于” 的答案。

标签: architecture erlang message-queue


【解决方案1】:

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

但是,如果您确实拥有数百万条消息,并且您已经设置了一个日志进程来订阅所有聊天,该怎么办?也就是说,至少,至少不是一个有利的情况。另一个不利因素是,单个 DB 表中将包含数以亿计的聊天消息行,而没有任何分区方案。显然,问题的一些划分是有序的。

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

考虑到这一点,如果您的数据本质上不是关系型的,则完全留在 Erlang 中可能就足以满足数据库要求,并使用 Mnesia 或 ETS/DETS 来持久存储消息。聊天数据本身没有任何关系,因此这可能是所有这些数据中最平滑的解决方案。如果您在聊天系统之外确实有一个真正的关系后端(也许聊天只是您提供的服务的一个方面),最好将事情留在更大的系统中,将聊天历史放在 Mnesia/ETS/DETS并编写一个强制检查,将聊天系统用户数据与规范的关系数据库同步。

无论如何,真正的问题是分区,每个通道一个记录器和一个数据库分区(至少,每月每个通道更可能一个分区)为您提供了一个很好的起点,可以将分区聚合成块可以理智地管理。另请注意,这种代码和数据分区允许您将问题分散到硬件和 erlang 节点上,因此任何地方的崩溃只会中断那里正在运行的任何通道和日志记录——让其他节点可用于恢复快速影响通道,并稍后同步数据分区,而不会遇到主要的“谁负责”之类的问题(不过,netsplits 仍然需要编写代码)。

【讨论】:

  • 表分片的好处!我们目前正在研究 CouchDB,但减少系统中移动部件的数量可能是个好主意。每秒不会有数十亿条消息,但肯定会有很多——这是针对现有的半流行服务的。
  • @lericson 在这种情况下,我会将崩溃视为临时灾难,让尚未到达目标(或记录器)的实时消息消失,但任何已命中记录器的消息都已打开某处的磁盘——所以 DETS 用于日志,但有一个每日/每小时/每月/ArbitrarySize 轮换方案,其中拥有您已登录到该点的 DETS 表的旧日志进程停止接受请求,并保存/传输其数据到某个仓库存放旧日志,同时一个新进程取而代之(制作转换块——最坏的情况是只要处理好一个进程就会产生)。
  • @lericson 只要你写入的磁盘没有起火(这就是为什么你在某个地方有一个像样的数据解决方案,对吧?)日志可以在最严重的中断后重新组装情况下,正常操作下是无缝的聊天记录历史。除非您是 Google 或 Facebook,否则 netsplits 应该很少见,以至于警报应该触发人为干预(因此您可以编写所选节点的崩溃/重新启动实用程序而不是 实际 共识代码)。在我看来,gee-whiz 实用程序越少越好;我会坚持为聊天日志服务使用简单的数据建模。
猜你喜欢
  • 2012-09-22
  • 2018-09-24
  • 1970-01-01
  • 2020-01-16
  • 2013-02-02
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
相关资源
最近更新 更多