当前位置: 首页 > news >正文

系统设计中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,因为它的延迟较低,牺牲可靠性来换取速度。

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 艾体宝干货 | 如何分析关键网络性能指标?持续接收样品试用申请!
  • 行为验证码——产品
  • easyadmin layui js监听返回结果,进行token验证防止连点
  • 详细说明Java中Map和Set接口的使用方法
  • 全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用
  • OpenFeign微服务调用组件
  • php yii2 foreach中使用事务,事务中使用了 continue
  • 快速排序(上)
  • 软件测试--python基础
  • 【Golang 面试 - 进阶题】每日 3 题(二)
  • 一篇文章解决Webpack
  • 【数据结构】了解哈希表,解决哈希冲突,用Java模拟实现哈希桶
  • 数据结构与算法 - 递归
  • 大龄程序员转型攻略:拥抱人工智能,开启新征程
  • 截止频率为声波传播的频率上、下限?如何区分两者的关系
  • gops —— Go 程序诊断分析工具
  • iOS | NSProxy
  • iOS小技巧之UIImagePickerController实现头像选择
  • KMP算法及优化
  • magento2项目上线注意事项
  • React+TypeScript入门
  • Redis 懒删除(lazy free)简史
  • v-if和v-for连用出现的问题
  • 大数据与云计算学习:数据分析(二)
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 京东美团研发面经
  • 入门级的git使用指北
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 责任链模式的两种实现
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​Java并发新构件之Exchanger
  • #100天计划# 2013年9月29日
  • #includecmath
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (4)(4.6) Triducer
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (安卓)跳转应用市场APP详情页的方式
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (转)Scala的“=”符号简介
  • (转)一些感悟
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • ::
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • @Pointcut 使用
  • @RequestBody的使用
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ C++ ] STL---string类的使用指南