可扩展的 MySQL 数据库,用于类似邮件的消息传递

Posted

技术标签:

【中文标题】可扩展的 MySQL 数据库,用于类似邮件的消息传递【英文标题】:Scalable MySQL database for mail-like messaging 【发布时间】:2011-01-15 05:24:24 【问题描述】:

假设我们有一个受欢迎的网站。我们需要在用户之间实现类似邮件的消息传递。 典型的解决方案是使用 2 个表:

用户(user_id)

消息(message_id、sender_id(引用 user_id)、receiver_id(引用 user_id)、主题、正文)。

这种方法有两个明显的局限性

    所有用户的所有消息都存储在一个表中,导致其负载很高并降低了整体数据库性能。 当有人需要同时向多个用户发送消息时,消息会被复制 (recipients_count) 次。

另一种解决方案使用 3 个表:

用户(user_id)

Sent_messages(sent_id, sender_id (references user_id), subject, body)

Received_messages(sent_id、receiver_id(引用 user_id)、主题、正文)

received_messages 的主题和正文是从 sent_messages 的相应字段复制而来的。

这种方法导致

    通过将信息从一个表复制到另一个表来非规范化数据库 用户实际上可以删除已发送/已接收的消息,而无需将其从接收者/发送者中删除。 消息占用大约 2 倍以上的空间 每个表的加载量大约减少了 2 倍。

那么问题来了:

    哪种设计更适合高负载和可扩展性? (我认为是第二个) 是否有另一种可以处理高负载的数据库设计?它是什么?有什么限制?

谢谢!

附:我知道在解决这些可扩展性问题之前,网站必须非常成功,但我想知道如果需要该怎么做。

更新

目前,对于第一个版本,我将使用 Daniel Vassallo 提出的设计。但是如果以后一切都OK的话,设计就改成第二个了。感谢 Evert 减轻了我对此的担忧。

【问题讨论】:

【参考方案1】:

在将邮件发送给多个收件人的情况下,您可能希望避免多次复制邮件正文。这是您可能需要考虑的另一个选项:

用户(user_id)

消息(message_id、sender_id、主题、 正文)

received_messages(message_id、user_id、address_mode、已删除)

这种模式可能更像推特而不是电子邮件,但它可能具有一些优势。

规则是:

一条消息只能由一个用户发送,在每条消息的 sender_id 中引用。 每个收件人都将在 received_messages 表中定义。 address_mode 字段可以定义消息是直接发送给收件人,还是作为抄送,或者可能作为密件抄送。这个字段显然是可选的。 收件人删除的邮件将在 received_messages 表中标记已删除标志。 需要使用新的 sender_id 重新创建转发和回复的邮件。然后可以修改消息正文。

这些是一些优点:

与原始问题中提到的两个选项相比,这占用的空间更少,尤其是在用户通常会将消息发送给多个收件人的情况下。 更容易缓存消息表,因为消息永远不会重复。 删除邮件的收件人不会删除邮件发送给该用户的信息。它只会在 received_messages 表中被标记为“已删除”。 您还会得到一个标准化模型。

对于大多数应用程序,如果您在上述模型中使用乐观隔离级别,则即使您期望消息以每秒几条的速度交换,也不应该出现性能问题。另一方面,如果您预计每秒有数百或数千条消息,那么可能确实需要考虑其他选项。

【讨论】:

谢谢!我也考虑过这个设计。实际上,在发布这个问题后,我(精神上:))将第一个设计修改为用户(user_id)消息(message_id,sender_id,receiver_id,message_content_id)消息内容(message_content_id,主题,正文)所以这两种设计都比第一个更好(在占用空间和表性能)。也许问题陈述必须是这样的:将所有消息存储在一个表中,还是将它们复制到两个表中更好?对性能的影响有多大?【参考方案2】:

一般来说,数据库大小不会是太大的问题。速度更为重要。

因此,我很想选择第二个选项。就像您提到的那样,它使删除消息之类的事情变得更加容易,而且我很确定这是一种非常常见的方法。

【讨论】:

以上是关于可扩展的 MySQL 数据库,用于类似邮件的消息传递的主要内容,如果未能解决你的问题,请参考以下文章

数据库:mysql内置功能-存储过程

8.7.4 mysql 内置功能 - 存储过程

知识点:Mysql 基本用法之存储过程

6-4 存储过程

RabbitMQ——简介

robotframework 做接口测试,怎么传raw格式的参数