【数据密集型系统设计】软件系统的可靠性、可伸缩性、可维护性

news2024/12/24 0:27:50

文章目录

  • 一. 数据密集型程序的特点以及遇到的问题
  • 二. 可靠性 : 即使出现问题,也能继续正确工作
    • 1 硬件故障
    • 2. 软件错误
    • 3. 人为错误
  • 二. 可伸缩性
    • 1. 描述负载与推特的例子
    • 2. 描述性能-延迟和响应时间
    • 3. 应对负载的方法
  • 四. 可维护性
    • 1. 可操作性:人生苦短,关爱运维
    • 2. 简单性:管理复杂度
    • 3. 可演化性:拥抱变化

本文讨论了软件系统的可靠性,可伸缩性和可维护性。

  • 可靠性(Reliability) 指高可用:及时发生故障(人为、bug、硬件服务)也能提供服务。一般高可用通过主备的概念去实现;

  • 可伸缩性(Scalability) 负载增加的情况下也有保持性能的策略,一般进行横向拓展;

  • 可维护性(Maintainability):这里强调抽象降低复杂度,并易于修改和适应新的应用场景。

 

一. 数据密集型程序的特点以及遇到的问题

现今很多应用程序都是 数据密集型(data-intensive) 的,而非 计算密集型(compute-intensive) 的。因此 CPU 很少成为这类应用的瓶颈,更大的问题(是内存)通常来自数据量、数据复杂性、以及数据的变更速度。

 

标准组件提供了应用的能力
数据密集型应用通常由标准组件构建而成,标准组件提供了很多通用的功能。例如,许多应用程序都需要:

  1. 存储数据,以便自己或其他应用程序之后能再次找到 (数据库,即 databases
  2. 加快读取速度(缓存,即 caches
  3. 允许用户按关键字搜索数据,或以各种方式对数据进行过滤(搜索索引,即 search indexes
  4. 向其他进程发送消息,进行异步处理(流处理,即 stream processing
  5. 定期处理累积的大批量数据(批处理,即 batch processing

 

使用多个组件的数据系统架构

应用代码将不同功能的工具缝合起来来一起服务,服务的接口想客户端隐藏这些实现细节。这个复合系统会有特定的保证:例如:缓存在写入时会作废或更新,以便外部客户端获取一致的结果。

应用架构的样子:

在这里插入图片描述

 

设计数据系统或服务时会遇到如下通用的问题:

  1. 当系统出问题时,如何确保数据的正确性和完整性?
  2. 当部分系统退化降级时,如何为客户提供始终如一的良好性能?
  3. 当负载增加时,如何扩容应对?
  4. 什么样的 API 才是好的 API?

 

这里我们讨论大多数系统中遇到的共性问题:

  • 可靠性(Reliability):

  • 可伸缩性(Scalability):面对数据、流量导致的内存增长,复杂性导致的可伸缩性变差有合理的办法应对系统的增长(数据量、流量、复杂性)。

  • 可维护性(Maintainability):

 

二. 可靠性 : 即使出现问题,也能继续正确工作

人们对可靠软件的典型期望包括

允许用户犯错、系统能防止未经授权的访问和滥用、在预期的负载和数据量下,性能满足要求。

1 硬件故障

硬盘的 平均无故障时间(MTTF, mean time to failure) 约为 10 到 50 年。因此从数学期望上讲,在拥有 10000 个磁盘的存储集群上,平均每天会有 1 个磁盘出故障。
 

增加单个硬件的冗余度来减少系统故障率:

为了减少系统的故障率,第一反应通常都是增加单个硬件的冗余度,例如:磁盘可以组建 RAID,服务器可能有双路电源和热插拔 CPU,数据中心可能有电池和柴油发电机作为后备电源,某个组件挂掉时冗余组件可以立刻接管。这种方法虽然不能完全防止由硬件问题导致的系统失效,但它简单易懂,通常也足以让机器不间断运行很多年。

 

多节点的高可用:

多节点的设计就是优先考虑 灵活性(flexibility)弹性(elasticity),而不是单机可靠性。

 

2. 软件错误

比起不相关的硬件故障往往可能造成更多的 系统失效

  1. 失控进程会用尽一些共享资源,包括 CPU 时间、内存、磁盘空间或网络带宽。
  2. 系统依赖的服务变慢,没有响应,或者开始返回错误的响应。
  3. 级联故障,一个组件中的小故障触发另一个组件中的故障,进而触发更多的故障

监控是有必要的

如果系统能够提供一些保证(例如在一个消息队列中,进入与发出的消息数量相等),那么系统就可以在运行时不断自检,并在出现 差异(discrepancy) 时报警。

 

3. 人为错误

尽管人类不可靠,但怎么做才能让系统变得可靠?最好的系统会组合使用以下几种办法:

  1. 将人们最容易犯错的地方与可能导致失效的地方 解耦(decouple)。比如提供一个功能齐全的非生产环境 沙箱(sandbox),使人们可以在不影响真实用户的情况下,使用真实数据安全地探索和实验。
  2. 确定测试边界
  3. 快速回滚配置变更,分批发布新代码
  4. 遥测(telemetry):配置详细和明确的监控,比如性能指标和错误率。监控可以向我们发出预警信号,并允许我们检查是否有任何地方违反了假设和约束。当出现问题时,指标数据对于问题诊断是非常宝贵的。

 

二. 可伸缩性

可伸缩性(Scalability) 是用来描述系统应对负载增长能力的术语。

系统今天能可靠运行,并不意味未来也能可靠运行。服务 降级(degradation) 的一个常见原因是负载增加,例如:系统负载已经从一万个并发用户增长到十万个并发用户,或者从一百万增长到一千万。

1. 描述负载与推特的例子

描述负载的方面,要注意最佳选择取决于系统架构与业务的流量

  1. 可能是每秒向 Web 服务器发出的请求
  2. 数据库中的读写比率
  3. 聊天室中同时活跃的用户数量
  4. 缓存命中率或其他东西

为了使这个概念更加具体,我们描述推特的例子。推特的两个主要业务是:

  • 发布推文: 用户可以向其粉丝发布新消息(平均 4.6k 请求 / 秒,峰值超过 12k 请求 / 秒)。
  • 主页时间线: 用户可以查阅他们关注的人发布的推文(300k 请求 / 秒)。

这里的一个需求是:当博主发布新的作品时,给关注他的人发送推文的逻辑。

方法说明
方法1发布推文时,只需将新推文插入全局推文集合即可。当一个用户请求自己的主页时间线时,首先查找他关注的所有人,查询这些被关注用户发布的推文并按时间顺序合并。
方法2维护消息队列,当发布新的博文时,提前给每个关注者发送到主页缓存中。所以读取开销小,因为写入时已经做了这部分工作。 因为写入时做更多的工作,写出时做更少的工作,这样查询时会更快。

 

方法1,2的优劣

  1. 推特的第一个版本使用了方法 1,但系统很难跟上主页时间线查询的负载。所以公司转向了方法 2,方法 2 的效果更好,因为发推频率比查询主页时间线的频率几乎低了两个数量级。
  2. 方法 2 的缺点是,发推现在需要大量的额外工作。平均来说,一条推文会发往约 75 个关注者,所以每秒 4.6k 的发推写入,变成了对主页时间线缓存每秒 345k 的写入。但这个平均值隐藏了用户粉丝数差异巨大这一现实,一些用户有超过 3000 万的粉丝,这意味着一条推文就可能会导致主页时间线缓存的 3000 万次写入!及时完成这种操作是一个巨大的挑战 —— 推特尝试在 5 秒内向粉丝发送推文。

要根据负载来选择方案,不能一概而论

  • 这里需要考虑的是,因为每个用户粉丝数的分布决定了扇出负载,而且需要在一定的时间内扇出,这里对系统的伸缩性(通过添加机器来分担负载?)也提出了要求,所以方法1,2不能一概而论。
  • 虽然在查询速度上慢,但方法1的扇出负载明显比方法2小,所以找到用户可接受的加载时间是需要权衡的。

 
最终的方案:
现在已经稳健地实现了方法 2,推特逐步转向了两种方法的混合。

  1. 大多数用户发的推文会被扇出写入其粉丝主页时间线缓存中。
  2. 少数拥有海量粉丝的用户(即名流)会被排除在外。当用户读取主页时间线时,分别地获取出该用户所关注的每位名流的推文,再与用户的主页时间线缓存合并,如方法 1。

这样就规避了这些名流带来的巨大扇出负载。

 

2. 描述性能-延迟和响应时间

一旦系统的负载被描述好,就可以研究当负载增加会发生什么。

  • 增加负载参数并保持系统资源(CPU、内存、网络带宽等)不变时,系统性能将受到什么影响?
  • 增加负载参数并希望保持性能不变时,需要增加多少系统资源?

这两个问题都需要性能数据,所以让我们简单地看一下如何描述系统性能。

  • 对于 Hadoop 这样的批处理系统,通常关心的是 吞吐量(throughput),即每秒可以处理的请求、或者在特定规模数据集上运行作业的总时间。
  • 对于在线系统,通常更重要的是服务的 响应时间(response time),即客户端发送请求到接收响应之间的时间。

 

  1. 响应时间:是客户所看到的,除了实际处理请求的时间( 服务时间(service time) )之外,还包括网络延迟和排队延迟;
  2. 延迟:是某个请求等待处理的 持续时长,在此期间它处于 休眠(latent) 状态,并等待服务。

响应时间的分布

  • 负载不同时:大多数请求是相当快的,但偶尔会出现需要更长的时间的异常值。这也许是因为缓慢的请求实质上开销更大,例如它们可能会处理更多的数据
  • 负载相同时:即使所有请求都花费相同时间的情况下,随机的附加延迟也会导致结果变化,例如:1. 上下文切换到后台进程,2. 网络数据包丢失与 3. TCP 重传,4. 垃圾收集暂停,5. 强制从磁盘读取的页面错误,6. 服务器机架中的震动,还有很多其他原因。

在这里插入图片描述

图展示了一个服务 100 次请求响应时间的均值与百分位数

 

3. 应对负载的方法

适应某个级别负载的架构不太可能应付 10 倍于此的负载。如果你正在开发一个快速增长的服务,那么每次负载发生数量级的增长时,你可能都需要重新考虑架构 — 或者更频繁。

应用系统的问题可能是读取量、写入量、要存储的数据量、数据的复杂度、响应时间要求、访问模式或者所有问题的大杂烩。

举个例子,用于处理每秒十万个请求(每个大小为 1 kB)的系统与用于处理每分钟 3 个请求(每个大小为 2GB)的系统看上去会非常不一样,尽管两个系统有同样的数据吞吐量

 

一个常用的方法是:

跨多台机器部署 无状态服务(stateless services) 非常简单,但将带状态的数据系统从单节点变为分布式配置则可能引入许多额外复杂度(分库分表、冷热分离)。出于这个原因,常识告诉我们应该将数据库放在单个节点上(纵向伸缩),直到伸缩成本或可用性需求迫使其改为分布式

 
根据业务情况来模拟负载情况:

一个良好适配应用的可伸缩架构,是围绕着 假设(assumption) 建立的:

  • 哪些操作是常见的?哪些操作是罕见的?这就是所谓负载参数。
  • 如果假设最终是错误的,那么为伸缩所做的工程投入就白费了,最糟糕的是适得其反。

 

四. 可维护性

众所周知,软件的大部分开销并不在最初的开发阶段,而是在持续的维护阶段,包括修复漏洞、保持系统正常运行、调查失效、适配新的平台、为新的场景进行修改、偿还技术债和添加新的功能。

我们在设计之初就尽量考虑尽可能减少维护期间的痛苦,从而避免自己的软件系统变成遗留系统。

为此,我们将特别关注软件系统的三个设计原则:

  • 可操作性(Operability): 便于运维团队保持系统平稳运行。
  • 简单性(Simplicity):从系统中消除尽可能多的 复杂度(complexity),使新工程师也能轻松理解系统。
  • 可演化性(evolvability): 使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配。也称为 可扩展性(extensibility)可修改性(modifiability)可塑性(plasticity)

1. 可操作性:人生苦短,关爱运维

尽管运维的某些方面可以,而且应该是自动化的,但在最初建立正确运作的自动化机制仍然取决于人。

一个优秀运维团队的典型职责如下(或者更多):

  • 监控系统的运行状况,并在服务状态不佳时快速恢复服务。
  • 跟踪问题的原因,例如系统故障或性能下降。
  • 了解系统间的相互作用,以便在异常变更造成损失前进行规避。
  • 预测未来的问题,并在问题出现之前加以解决(例如,容量规划)。
  • 建立部署、配置、管理方面的良好实践,编写相应工具。
  • 执行复杂的维护任务,例如将应用程序从一个平台迁移到另一个平台
  • 定义工作流程,使运维操作可预测,并保持生产环境稳定。
  • 铁打的营盘流水的兵,维持组织对系统的了解

数据系统可以通过各种方式使日常任务更轻松:

  • 通过良好的监控,提供对系统内部状态和运行时行为的 可见性(visibility)
  • 为自动化提供良好支持,将系统与标准化工具相集成
  • 避免依赖单台机器(在整个系统继续不间断运行的情况下允许机器停机维护)。
  • 提供良好的文档和易于理解的操作模型(“如果做 X,会发生 Y”)
  • 提供良好的默认行为,但需要时也允许管理员自由覆盖默认值。
  • 有条件时进行自我修复(how),但需要时也允许管理员手动控制系统状态。
  • (系统)行为可预测,最大限度减少意外。

 

2. 简单性:管理复杂度

复杂度(complexity) 有各种可能的症状,例如:状态空间激增、模块间紧密耦合、纠结的依赖关系、不一致的命名和术语、解决性能问题的 Hack、需要绕开的特例等等。

降低复杂度能极大提高软件可维护性

因为复杂度导致维护困难时,预算和时间安排通常会超支。在复杂的软件中进行变更,引入错误的风险也更大:当开发人员难以理解系统时,隐藏的假设、无意的后果和意外的交互就更容易被忽略。 相反,降低复杂度能极大地提高软件的可维护性,因此简单性应该是构建系统的一个关键目标。

 

通过抽象来降低复杂度

用于消除 额外复杂度 的最好工具之一是 抽象(abstraction)
一个好的抽象可以将大量实现细节隐藏在一个干净,简单易懂的外观下面。比起重复造很多轮子,重用抽象不仅更有效率,而且有助于开发高质量的软件。抽象组件的质量改进将使所有使用它的应用受益。

 

3. 可演化性:拥抱变化

系统的需求处于常态的变化中,例如:你了解了新的事实、出现意想不到的应用场景、业务优先级发生变化、用户要求新功能、新平台取代旧平台、法律或监管要求发生变化、系统增长迫使架构变化等。

在组织流程方面,敏捷(agile) 工作模式为适应变化提供了一个框架。敏捷社区还开发了对在频繁变化的环境中开发软件很有帮助的技术工具和模式,如 测试驱动开发(TDD, test-driven development)重构(refactoring)

 

修改数据系统并使其适应不断变化需求的容易程度,是与 简单性抽象性 密切相关的:简单易懂的系统通常比复杂系统更容易修改。

 

一个应用必须满足各种需求才称得上有用。

  • 一些 功能需求(functional requirements,即它应该做什么,比如允许以各种方式存储,检索,搜索和处理数据)
  • 一些 非功能性需求(nonfunctional,即通用属性,例如安全性、可靠性、合规性、可伸缩性、兼容性和可维护性)。在本章详细讨论了可靠性,可伸缩性和可维护性。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1793770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go语言-切片底层探索 —— 补充篇:切片和底层数组到底是什么关系?

之前的切片探索中,上篇通过一道算法题目,了解到切片的两大特性:一是:切片是引用类型,指向底层数组,修改其底层数组的时候,会影响切片中的值。二是:向切片中添加元素的时候&#xff0…

ES6真题合集(一)

ES6真题合集(一) 1. var、let、const之间的区别2. ES6中数组新增了哪些扩展2.1 扩展运算符2.2 Array.from() 方法2.3 Array.of() 方法2.4 find() 和 findIndex() 方法2.5 箭头函数2.6 模板字符串 3. ES6中对象新增了哪些扩展3.1 属性的简写3.2 属性名表达…

[SQL-SERVER:数据库安全及维护]:MSSM工具对用户进行用户授权和角色授权操作

文章目录 直接为用户授权(20分)1. 创建登录TLogin,自行指定登录密码服务器层面选择 安全性 > 点击 登录名 > 点击右键 > 点击 新建登录名 > 选择sqlserver验证 > 关闭强制登录更改密码异常解决:sqlserver 配置管理…

Docker+JMeter+InfluxDB+Grafana 搭建性 能监控平台

JMeter原生报告的缺点: 无法实时共享 报告信息的展示不美观 需求方案 为了解决上述问题,可以通过 InfluxDB Grafana解决 : InfluxDB :是一个开源分布式指标数据库,使用 Go 语言编写,无需外部依赖 应用&am…

【C++】类和对象——构造和析构函数

目录 前言类的六个默认构造函数构造函数1.构造函数的概念2.构造函数的特性 初始化列表1.构造函数整体赋值2.初始化列表 析构函数1.析构函数的概念2.析构函数的特性 前言 类和对象相关博客:【C】类和对象   我们前面一个内容已经讲了关于类好对象的初步的一些知识&…

Linux——nginx部署

部署Nginx 构建Nginx服务器 (实验需要DNS支持,或添加hosts条目,例如: ) 安装Nginx(yum安装即可) 安装依赖软件包: 重启、启用服务并查看服务状态: 默认页面&#xff0…

AIGC会带来失业潮吗?紧紧跟时代第一步,如何学习AIGC

会,但AI淘汰的始终是跟不上时代的人。 现在很多公司都有AI培训,不仅GPT,还有Midjourney、Stable DIffusion等一系列AI工具。 像我们公司虽然今年招的少,但也会对新招的应届生统一进行AI培训。 用任正非先生的话来说就是&#x…

ubuntu top命令的参数和快捷键

命令选项 -1 单个、所有cpu信息切换 top -1-b 批处理 top -b > top.txt这将保存top命令的输出到文件,直到手动终止或关机。所以使用这个命令要注意和其他命令配合,否则文件速度增长会很快。 在文件中,将会重复输入top命令。 -c 切换命…

干货!以医疗行业为例,讲解数据安全级别划分以及归纳敏感数据的处理策略

数据分类分级是一项基础工作,也是提供数据分级保护的基础措施之一,是企业长期的一项技术、管理措施。企业通过制定数据分类分级策略、模板、管理规范能够有助于帮助企业梳理清楚企业数据资产,在面向合规监管、内部数据安全控制时能够提供更完…

pyspark中使用mysql jdbc报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决

报错信息: py4j.protocol.Py4JJavaError: An error occurred while calling o33.load. : java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 我的解决方法: 这个报错就是提示你找不到jar包,所以你需要去下载一个和你mysql版本匹配的j…

摸鱼大数据——Hive调优16-19

16、JVM 重用 此操作, 在hive2.x已经不需要配置了, 默认支持 jvm重用: 默认情况下, container资源容器 只能使用一次,不能重复使用, 开启JVM重用, 运行container容器可以被重复使用,在hive2.x已经默认支持了 17、推测执行 调优举例: 大数据小组,假设…

Android14 WMS-窗口绘制之relayoutWindow流程(二)-Server端

本文接着如下文章往下讲 Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端-CSDN博客 然后就到了Server端WMS的核心实现方法relayoutWindow里 WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server…

QT系列教程(9) 主窗口学习

简介 任何界面应用都有一个主窗口,今天我们谈谈主窗口相关知识。一个主窗口包括菜单栏,工具栏,状态栏,以及中心区域等部分。我们先从菜单栏说起 菜单栏 我们创建一个主窗口应用程序, 在ui文件里的菜单栏里有“在这里输入”的一个…

四、Window整理右键扩展

一、桌面右键和文件右键扩展整理 简而言之整理下面图示内容 桌面右键: 对文件右键: 工具:火狐自带工具 二、新建扩展管理 简而言之整理下面图示内容 Win R输入regedit 寻找:计算机\HKEY_CURRENT_USER\Software\Microsof…

中科数安 | 透明加密防泄密系统!如何有效防止企业内部核心数据资料外泄?

中科数安提供的透明加密防泄密系统是一种专为企业设计的数据保护解决方案,它通过以下关键特性有效防止企业内部核心数据资料外泄: PC地址:——www.weaem.com 自动智能透明加密:系统能够在操作系统级别无缝集成,对指定类…

重生之 SpringBoot3 入门保姆级学习(15、内容协商返回不同数据类型)

重生之 SpringBoot3 入门保姆级学习&#xff08;15、内容协商返回不同数据类型&#xff09; 3.3.3 改变 Accept 实现内容协商3.3.4 改变 application.proerties 实现内容协商 3.3.3 改变 Accept 实现内容协商 添加支持写出 xml 内容的 Maven 依赖并刷新 Maven <!-- …

日语里「ずつ」和「づつ」有什么不同,柯桥成人日语培训

在生活中&#xff0c;我们常用「1人ずつ」「一歩ずつ」表示固定数量的重复出现&#xff0c;但有时候也会写作「1人づつ」「一歩づつ」&#xff0c;究竟哪种写法才是正确的呢&#xff1f;今天这篇文章将对「ずつ」和「づつ」的正确用法进行说明。 01 使用情况 根据日本文部科学…

RLHF(从人类反馈中进行强化学习)详解(三)

在经过了前两节的内容学习之后&#xff0c;我们对于RLHF&#xff08;从人类反馈中进行强化学习&#xff09;有了比较深入的认知&#xff0c;并且初步了解了RLHF中偏好数据集的引入&#xff0c;奖励模型的设置以及baseLLM的训练过程。在本节的学习中&#xff0c;我们将深入LLM的…

Visual Studio Installer 点击闪退

Visual Studio Installer 点击闪退问题 1. 问题描述2. 错误类型3. 解决方法4. 结果5. 说明6. 参考 1. 问题描述 重装了系统后&#xff08;系统版本&#xff1a;如下图所示&#xff09;&#xff0c;我从官方网站&#xff08;https://visualstudio.microsoft.com/ ) 下载了安装程…

如何把几个pdf文件合成在一个pdf文件

PDF合并&#xff0c;作为一种常见的文件处理方式&#xff0c;无论是在学术研究、工作汇报还是日常生活中&#xff0c;都有着广泛的应用。本文将详细介绍PDF合并的多种方法&#xff0c;帮助读者轻松掌握这一技能。 打开 “轻云处理pdf官网” 的网站&#xff0c;然后上传pdf。 pd…