写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/system/design-system
设计一个支持数百万用户的系统是极具挑战性的,它是一段需要持续优化和不断改进的旅程。在这篇博客中,我们将构建一个支持单个用户的系统,并逐步扩展到能够服务于数百万用户。在阅读这篇博客之后,你将掌握一些有助于破解系统设计面试题的技术。
在这段旅程中,你会学到:
- 初始设计:如何从一个简单的系统开始,满足最基本的用户需求。
- 扩展策略:使用不同的技术和架构模式来提升系统的扩展性。
- 性能优化:识别并解决性能瓶颈,确保系统在高负载下依然稳定高效。
- 容错和恢复:设计系统以应对故障,并快速恢复,保证高可用性。
- 监控和调试:实施有效的监控和调试策略,确保系统的健康运行。
通过这些内容,你不仅能更好地理解如何从零开始构建一个大规模系统,还能在系统设计面试中脱颖而出。接下来,我们将逐步深入探讨每个阶段的关键技术和最佳实践。
单服务器设置
千里之行,始于足下,构建一个复杂的系统也不例外。我们需要从一个简单的开始,一切都运行在一台服务器上。这一阶段的目标是构建一个功能完整、易于维护的初始系统。图1展示了单服务器设置的示意图,在这个设置中,所有东西都运行在同一台服务器上:包括Web应用、数据库、缓存等。
为了理解这一设置,研究请求流程和流量来源是很有帮助的。首先,让我们看看请求流程(图2):
- 用户通过域名(如 api.mysite.com)访问网站。通常,域名系统(DNS)是由第三方提供的付费服务,并不托管在我们自己的服务器上。
- 互联网协议(IP)地址会返回给浏览器或移动应用程序。在示例中,返回的IP地址是15.125.23.214。
- 一旦获得IP地址,超文本传输协议(HTTP)请求会直接发送到你的Web服务器。
- Web服务器返回用于渲染的HTML页面或JSON响应。
接下来,让我们来探讨流量来源。Web服务器的流量来源有两个:Web应用和移动应用。
Web应用:它使用服务器端语言(如Java、Python等)处理业务逻辑和存储等,并使用客户端语言(如HTML和JavaScript)进行展示。
移动应用:HTTP协议是移动应用和Web服务器之间的通信协议。JavaScript对象表示法(JSON)通常用作API响应格式,因为它简单易用。下面是一个JSON格式的API响应示例:
// GET /users/12 – Retrieve user object for id = 1
{"userId": 1,"userName": "john_doe","email": "john_doe@example.com","profile": {"age": 30,"gender": "male","location": "New York"}
}
数据库
随着用户基础的增长,一台服务器已无法满足需求,我们需要多台服务器:一台用于处理Web/移动流量,另一台用于数据库(图3)。将Web/移动流量(Web层)和数据库(数据层)服务器分离,可以使它们独立扩展。
数据库的选择
你可以在传统的关系型数据库和非关系型数据库之间进行选择。让我们来探讨它们的区别。
关系型数据库也称为关系型数据库管理系统(RDBMS)或SQL数据库。最流行的有MySQL、Oracle数据库、PostgreSQL等。关系型数据库以表格和行的形式表示和存储数据。你可以使用SQL在不同的数据库表之间执行连接操作。
非关系型数据库也称为NoSQL数据库。流行的有CouchDB、Neo4j、Cassandra、HBase、Amazon DynamoDB等。这些数据库分为四类:键值存储、图存储、列存储和文档存储。非关系型数据库一般不支持连接操作。
对于大多数开发人员来说,关系型数据库是最佳选择,因为它们已经存在了超过40年,并且在历史上表现良好。然而,如果关系型数据库不适合你的特定用例,那么探索关系型数据库之外的选项是很重要的。非关系型数据库可能是正确的选择,如果:
- 你的应用程序需要超低延迟。
- 你的数据是非结构化的,或者你没有任何关系数据。
- 你只需要序列化和反序列化数据(如JSON、XML、YAML等)。
- 你需要存储大量数据。
关系型数据库的特点:
- 数据结构化
关系型数据库使用表格来组织数据,数据结构清晰,便于管理和查询。 - 支持事务
关系型数据库支持ACID(原子性、一致性、隔离性、持久性)事务,确保数据操作的可靠性。 - 强大的查询能力
使用SQL可以方便地进行复杂的查询和数据分析,支持连接操作,适合关系数据。
非关系型数据库的特点:
- 高性能
非关系型数据库通常具有较低的延迟和较高的吞吐量,适合高性能需求的应用。 - 灵活的数据模型
非关系型数据库支持多种数据模型,如键值对、文档、列族和图结构,适合非结构化或半结构化数据。 - 可扩展性
非关系型数据库通常更容易横向扩展,可以处理大规模的数据和高并发请求。
选择合适的数据库:
- 如果你的应用程序主要处理关系数据,并且需要执行复杂的查询和事务操作,关系型数据库是理想的选择。
- 如果你的应用程序需要处理大量非结构化数据、高性能需求或者需要简单的键值存储,非关系型数据库可能更合适。
垂直扩展 VS 水平扩展
垂直扩展,也称为“向上扩展”(scale up),指的是通过增加服务器的处理能力(如CPU、内存等)来提升性能。水平扩展,也称为“向外扩展”(scale-out),则是通过增加更多服务器到资源池中来进行扩展。
当流量较低时,垂直扩展是一个很好的选择,其主要优势在于简单。然而,垂直扩展存在一些严重的限制:
- 硬性限制
垂直扩展有一个硬性限制,