系统设计中15 个最重要的权衡

系统设计的第一法则:一切都与权衡有关。

在设计系统时,我们需要决定要包含哪些功能以及要忽略哪些功能。每次我们做这个决定时,我们都在进行权衡。在本文中,我们将探讨系统设计中遇到的15个最常见的权衡问题,并使用实际示例进行说明:

1. 可扩展性与性能

可扩展性涉及系统的规模:"系统是否可以扩展以处理更多的流量和数据?"

性能 涉及系统的速度:"系统能多快完成任务?"

们通常相互矛盾,改进一个可能会影响另一个。

示例:向系统添加更多机器可以使其更具可扩展性,但是管理这些机器和协调任务的复杂性可能会导致性能的延迟。

2. 垂直扩展与水平扩展

垂直扩展 涉及向现有服务器添加更多资源(例如 CPU、RAM),而水平扩展意味着添加更多服务器。

垂直扩展更简单,但单台计算机再怎么升级也是存在上限的,而且存在单点故障问题。如果机器发生故障,整个系统都不可用。水平扩展允许几乎无限的扩展,但带来了管理分布式系统的复杂性。

**示例:初创公司可能会通过增加CPU和RAM来垂直扩展其服务器以应对增加的负载。随着公司的发展,它可能会转向水平扩展,通过增加服务器来分散负载。

3. 延迟与吞吐量

延迟 衡量数据在网络中传输所需的时间。吞吐量是指指在特定时间内通过网络的数据平均量。

低延迟系统对于实时应用至关重要,而高吞吐量系统对于数据密集型应用至关重要。

**示例:**在线游戏需要低延迟来提供玩家之间的实时互动。数据分析服务优先考虑吞吐量,以以处理和分析大量数据集。

4. SQL 与 NoSQL 数据库

**SQL(关系数据库)**建立在关系模型之上,该模型将数据组织成由行和列构成的表表,并使用唯一的键来标识每一行。这些数据库结构严谨,提供强大的查询语言,非常适合处理复杂的查询和事务。例如:MySQL、PostgreSQL。然而,SQL数据库在水平扩展上可能具有挑战性。

**示例:**银行使用 SQL 数据库进行交易管理。这些数据库确保所有交易都得到可靠处理,维护准确的账户余额和交易历史。

**NoSQL(非关系数据库)**提供灵活性并易于扩展,但可能会牺牲类似 SQL 的查询功能和 ACID 事务。NoSQL 遵循 BASE 属性,即基本可用、软状态、最终一致性......例如,它可能无法始终满足一致性,但最终会变得一致。因此,它牺牲了 ACID 属性,但并非完全牺牲!

NoSQL 适合处理大量非结构化或半结构化数据,例如:Cassandra、Amazon DynamoDB。NoSQL有多种类型,包括文档、键值、宽列、文档和图形存储。

**示例:**Netflix等公司使用NoSQL进行实时推荐引擎。NoSQL数据库可以快速处理大量多样化的数据(观看记录、评分、偏好),为数数亿用户提供个性化内容推荐。

5.一致性与可用性(CAP定理)

一致性意味着每次访问系统时都会获得最新数据。

**示例:**在淘宝等电商系统中,当客户下订单时,系统会确保立即更新库存水平。这种一致性可防止其他客户在缺货时订购同一商品。

可用性就是确保系统始终正常运行,即使系统的某些部分出现问题。

**示例:**在在线消息服务中,可用性确保即使部分服务器宕机,你仍然可以发送和接收消息。

根据CAP理论,在分布式系统中,你只能保证一致性、可用性和分区容忍性中的两个。

在一致性和可用性之间进行选择取决于您的系统想要提供的用户体验什么更重要。

6. 强一致性与最终一致性

在分布式系统中,数据存储在多个位置,确保每个人同时看到相同的数据可能具有挑战性。这就是强一致性和最终一致性的概念发挥作用的地方。强一致性意味着一旦发生数据更新,对该数据的任何后续访问都能获取到最新值。

**示例:**在银行系统中,当您将钱从一个账户转移到另一个账户时,系统会立即更新余额。

而最终一致性则意味着更新在系统的所有节点上可见之前可能会有延迟。但是,可以保证的是,如果没有新的更新,最终对该数据的所有访问都将返回更新后的值。

**示例:**在 Instagram 等社交媒体平台上,当您发布新照片时,它可能不会立即出现在所有关注者的动态中。但是,经过短暂的时间后,每个人都将能够看到这张新照片。

7. Read-Through vs Write-Through Cache

缓存是一种通过将经常访问的数据存储在更快的存储介质中来加快数据访问的技术。说到缓存策略,"Read-Through"和"Write-Through"是两种常见的策略。

Read-Through策略在请求数据时会先检查缓存。如果数据不存在(缓存未命中),则会从较慢的主存储加载到缓存中,然后再返回。

它适用于读取频繁但不经常更新的应用程序。

示例:在在线商店中,当客户第一次查看产品时,产品详情从数据库中获取并存储到缓存中。后续查看则从缓存中获取,加快响应时间并减少数据库查询。

Write-Through同时将数据更新写入缓存和主存储,确保数据最新并降低数据丢失风险。

这对于写操作频繁的应用程序非常有益。所有写入都会立即反映在缓存和主存储中。

示例:电影票预订系统使用Write-Through策略,通过立即在缓存和数据库中记录预订来防止超额预订。

8.批处理与流处理

批处理 涉及在一段时间内收集数据,然后一次性处理所有数据。流处理 意味着实时处理数据,一旦数据到达就立即处理。

示例:信用卡公司使用批处理来生成每日账单和报表。为了检测欺诈,他们实施流处理来实时分析交易并立即标记可疑活动。

9.同步与异步处理

同步处理是指任务一个接一个地执行。必须完成一个任务才能开始下一个任务,系统会等待结果后再继续执行。

示例:当您进行线购物时,付款过程是同步的。单击"立即支付"后,你等待交易处理。网站在确认支付成功前不会让你继续。

异步处理允许任务在后台运行,不需要等待其完成就可以开始本任务。

示例:在社交媒体上上传照片是在后台异步进行的。您可以在照片上传时继续滚动或退出应用程序。

10.有状态架构与无状态架构

有状态系统会记住过去的交互。它存储有关当前会话的信息,从而可以在后续交互中保持连续性和上下文,而无需每次都从头开始。

**例如:**在线购物时,当您将商品添加到购物车时,网站会记住您的选择。如果您离开以浏览更多商品,然后返回购物车,您的商品仍在那里,等待您结账。

无状态系统不会跟踪过去的交互。每个请求都被视为新请求,不会保留先前请求的任何信息。

示例:许多 RESTful Web 服务运行时不会记住过去的请求。例如,当您向公共 API 查询天气信息时,您需要在每次请求中提供所有必要的详细信息(如位置)。

11. 长轮询与 WebSockets

长轮询是一种技术,客户端向服务器请求数据,服务器保持请求打开,直到有新信息可用。收到数据后,客户端立即发送新请求,从而实现即时更新。

**示例:**社交媒体平台的通知系统。浏览器不断向服务器查询新通知,当出现新通知或发生超时时,服务器会做出响应。

WebSockets通过单个长期连接的全双工通信通道,使服务器和客户端可以在数据可用时立即相互发送数据,而无需等待另一方的请求。

示例:在多人在线游戏中,WebSockets通过客户端和服务器之间的持久连接,实时共享玩家动作和游戏更新。

12. 规范化与非规范化

数据库设计中的规范化涉及将数据拆分到相关表中,以确保每条信息只存储一次。其目的是减少冗余并提高数据完整性。

示例:客户数据库可以有两个独立的表:一个用于客户详细信息,另一个用于订单,避免每个订单的客户信息重复。

另一方面,非规范化是将数据重新组合到更少的表中以提高查询性能。这通常会在数据库中引入冗余(重复信息)。

示例:博客网站可以将最新评论与帖子存储在同一张表中(非规范化),以加快帖子和评论的显示,而不是将它们分开存储(规范化)。

13. 单体架构与微服务架构

单体架构将应用的所有功能作为单一、不可分割的单元运行。所有功能都打包在一个进程中,通常作为单一代码库进行开发、测试和部署。

微服务 架构则是将应用分解为一组小型、松散耦合的服务,每个服务都专注于特定功能,并通过轻量级通信协议(如HTTP)相互交互。

单体架构简单易部署,适合小型应用程序或团队。但是,随着应用程序的增长,它可能会减慢开发速度并使可扩展性变得复杂。微服务架构提高了可扩展性和开发速度。但是,它引入了服务管理、数据一致性的复杂性,并增加了通信开销。

**示例:**为简单起见,小型 Web 应用程序可能以单体式架构开始。随着规模的增长,它可以演变为微服务架构,拆分为更小、可独立扩展的服务,从而实现更好的灵活性和可扩展性。

14. REST 与 GraphQL

REST是一个成熟的API标准,提供了简洁性并支持多种格式。使用REST API时,您可以通过访问多个端点来收集数据。

GraphQL提供了更高效的数据获取,减少了请求次数,但需要更高的学习曲线和更多的前期设计。

在 GraphQL 中,您可以向 GraphQL 服务器发送一个包含具体数据需求的查询。服务器然后返回一个JSON对象,其中包含了这些需求的数据。

15. TCP 与 UDP

TCP 和 UDP 是TCP/IP协议中传输层的两种协议。

TCP(传输控制协议) 可确保您的消息完好无损地按照发送的顺序到达。它在发送方和接收方之间建立连接,检查数据是否正确接收,必要时会重新发送丢失的数据。TCP 非常适合用于对可靠性要求很高的应用程序,比如电子邮件服务。

UDP(用户数据报协议) 牺牲了可靠性来换取速度,适用于视频流等对时间敏感的应用程序,在这种情况下,传输过程中丢失一些数据也没关系。UDP发送数据时无需建立连接,也不检查数据是否接收或顺序是否正确。在线游戏和直播服务可能会选择 UDP,因为它的延迟较低,牺牲可靠性来换取速度。

每个权衡的选择因具体项目而异。

理解这些权衡可以帮助您作出明智的选择来设计高性能、可扩展和用户体验优秀的系统。

相关推荐
七灵微2 天前
进程与线程以及如何查看
linux·系统架构
oioihoii2 天前
桌面图形界面生成原理:从流水灯到电脑屏幕
系统架构
颯沓如流星3 天前
软件架构设计方法之The Clean Architecture 整洁架构
架构·系统架构
柔弱女子爱java3 天前
spring专题笔记(五):依赖注入--p命名空间注入、c命名空间注入、util命名空间
java·笔记·后端·spring·架构·系统架构
云空3 天前
《 QT 5.14.1 类库模块列表详述》
开发语言·qt·系统架构
星原飞火4 天前
2-2-18-16 QNX系统架构之自适应分区
车载系统·系统架构·qnx·blackberry
重生之我是数学王子5 天前
ARM原理
arm开发·系统架构
silver6875 天前
中间件介绍
系统架构
亭墨5 天前
linux0.11源码分析第二弹——setup.s内容
linux·驱动开发·学习·系统架构
田超凡7 天前
M4Pro内核MacOS brew安装docker爬坑
微服务·云原生·java-ee·系统架构