在这个系统设计场景中,我们被要求设计一个类似WhatsApp的消息应用程序。
虽然在实际的讨论中可能会重点讨论该应用程序的一个或多个功能,但在本文中,我们将对系统的架构进行一个高层次的概述,然后可以根据需要深入探讨具体的领域。
明确功能需求
通过向业务方提问来缩小范围,因为在一个小时内设计整个WhatsApp平台是不现实的:
主要用例: 该应用的主要目的是发送、检查和接收消息,以及阅读和标记消息为已读。
群组: 我们将不涉及群组消息,只考虑一对一消息。•内容类型: 我们只支持文本消息,不支持图片或视频。
明确非功能需求
规模: 首先,我们来谈谈规模,即系统的大小和消息的处理量。假设每天发送100亿条消息,并且我们计划在一年内将其翻倍。
可用性: 在可用性方面,我们希望系统高度可用并始终运行。
延迟: 至于系统延迟,我们希望它几乎是即时的,因此大多数API请求应在100毫秒内完成。
估算:数据计算
每天100亿条消息,约为10B消息 / 86,400秒每天 = 115,740条消息每秒(MPS)。在一年内翻倍意味着我们应计划为115,740 * 2 = 231,480 MPS。
假设每条消息200字节,每日存储量为10B消息 * 200字节 = 2 TB。年存储量及增长约为2TB * 365天 * 2 = 1.5 PB。
需要注意的是,我们计算的是平均值,但系统需要处理高峰流量,这可能比平均MPS高得多。我们可能需要根据高峰时间进行扩展。
接口API设计
我们可能会使用RESTful API风格以获得更广泛的兼容性。以下是可能的端点细分:
- 发送消息 (POST /messages): 请求体包括接收者的ID和消息内容。成功响应(200)返回唯一的消息标识符。错误代码(400, 500)处理缺少参数或服务器问题。
- 检查新消息 (GET /messages): 响应为包含未读消息的数组(200)或如果没有则返回204。
- 获取特定消息 (GET /messages/:messageId): 返回特定消息(200)或未找到则返回404。
- 标记消息为已读 (PUT或PATCH /messages/:messageId): 成功响应(200)确认更改,而404表示未找到消息。
其他考虑: 我们将集成WebSockets以实现实时更新。API将处理认证和初始连接建立。并且分页可能是‘检查新消息’端点所需的。安全措施,如输入验证,也是必要的。
系统设计
移动应用:用户的主要界面将是移动应用(iOS, Android)。此应用程序处理发送和接收消息、联系人管理和对话。
负载均衡器:为了有效处理传入请求,我们将使用负载均衡器来分配流量到多个服务器。这样可以提高应用程序的可靠性。
API服务器:所有请求将进入API服务器,这些服务器处理我们之前概述的RESTful API,管理消息逻辑。API服务器本身可以是无状态的,这样我们可以水平扩展(添加更多服务器)以应对流量增长。
WebSocket连接:类似WhatsApp的应用程序严重依赖WebSockets进行实时通信。聊天服务器将与移动应用程序保持持久的WebSocket连接。当消息到达时,可以立即推送到接收者的设备。
消息分发器:接下来,我们将有一个消息分发器服务,该服务的主要目的是将API服务器与直接数据库写入解耦,这对于处理高写入量尤其重要。
消息队列,如Kafka或RabbitMQ,是这里的理想选择。其工作原理如下:
- API服务器接收到“发送消息”的POST请求。
- 它将消息放在队列中,并迅速向客户端返回成功/确认。
- 独立的工作进程异步从队列中读取并将消息写入数据库。
数据库 (NoSQL): 我们同意最终一致性是可以接受的,这使得NoSQL成为高消息量的可扩展选择。
以下是两个强有力的选择:
- Cassandra: 以可扩展性、高可用性和写性能而闻名的宽列存储。特别适合我们预期的高写入量和简单读取模式(主要通过ID获取消息)。
- DynamoDB: AWS提供的完全托管的键值和文档数据库。如果我们想要一个最小维护的数据库解决方案且能轻松扩展,这非常有利。
分片和分区: 由于没有单一数据库可以处理我们1.5 PB的存储需求,因此分片(水平分区)数据是至关重要的。
但是我们将如何分片和分区这些数据,以及这些API服务器如何知道从哪里请求这些数据?
我们可以基于userId进行分区。所有涉及用户的消息将驻留在同一个分片/分区中。而我们的API服务器有两种可能的方法来定位数据:
- 一致性哈希环: 数据位置可以基于分区键确定,允许API服务器直接路由请求到正确的数据库分片。
- 元数据服务: 一个独立的服务保持分区键到分片位置的映射。API服务器首先查询此服务,然后进行数据库调用。
结论和当前系统瓶颈
这概述了类似WhatsApp应用程序的主要架构。现在,让我们看看我们当前系统中的潜在瓶颈和改进领域:
- 数据库写入: 高写入量是一个潜在的瓶颈。分片、消息队列和优化的数据库选择是关键。
- 端到端加密: WhatsApp模型非常强调安全性。实现端到端加密将是一个关键讨论点。
- 群组聊天: 此功能为消息路由和存储带来了额外的复杂性。
- 媒体处理: 我们可以实现一个处理图像和视频上传的系统,这里使用压缩以及多种存储大小的缩略图。