第1章 可靠性,可扩展性,可维护性

Joyine 2019-07-01

第1章 可靠性,可扩展性,可维护性

数据密集型程序:问题通常来自数据量,数据复杂性,以及数据的变更速度。

数据库:存储数据,以便自己或其他应用程序之后能再次找到。

缓存:记住开销昂贵的操作的结果,加快读取速度。

搜索索引:允许用户按关键字搜索数据,或以各种方式对数据进行过滤。

流处理:向其他进程发送消息,进行异步处理。

1.关于数据系统的思考

1.1.可靠性

1.1.1.什么是可靠性?

系统在发生硬件故障,软件故障,或人为错误时,任然可以正常工作。

1.1.2.影响可靠性的因素

a.硬件故障

当集群足够大,硬件故障总是会发生,可能存在硬盘崩溃,内存出错,机房断点,有人拔错网线…等等,都会造成硬件不可用的状态。

b.软件错误

主要有:

  • 接收特定的错误输入,导致所有的应用服务器实例崩溃的bug。
  • 失控进程会占用一些共享资源,包括CPU,内存,磁盘空间或网络带宽等。
  • 级联故障,一个组件中的小故障触发另一个组件中的故障,进而触发更多的故障。

软件中的系统故障没有速药,但是有很多小办法:

  • 仔细考虑系统中的假设和交互。
  • 彻底的测试。
  • 进程隔离
  • 允许进程蹦崩溃并重启
  • 测量,监控并分析生产环境中的系统行为

c.认为错误

人类是不可靠的。

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

  • 以最小化犯错机会的方式设计系统。例如:精心设计的抽象,API和管理后台使做对事情更容易,搞砸事情更困难。
  • 将人们最容易犯错的地方与可能导致失效的地方解耦。特别是提供一个功能齐全的非生产环境沙箱,使人们可以在不影响用户的情况下,使用真实数据安全地探索和实验。
  • 各层次进行彻底的测试,从单元测试,全系统集成测试到手动测试。
  • 允许从人为错误中简单快速地恢复,以最大限度地减少失效情况带来的影响。例如:快速回滚配置变更,分批发布新代码,并提供该数据重算工具。

1.2.可扩展性

1.2.1.什么是可以扩展性?

有合理的办法应对系统的增长(数据量,流量,复杂性),可扩展性是用来描述系统对应负载均衡增长能力的术语。

讨论可扩展性意味着考虑诸如:如果系统以特定方式增长,有什么选项可以应对增长?或 如何增加计算资源来处理额外的负载 等问题。

1.2.2.描述负载

负载可以用一些称为“负载参数”的数字来描述。

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

1.2.3.描述性能

一旦系统的负载被描述好,就可以研究当前负载增加会发生什么。我们可以从两个角度来看:

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

1.2.4.应对负载的方法

当负载参数增加时,如何保持良好的性能?

两种扩展思路:纵向扩展(转向更强大的机器),横向扩展(将负载分布到多台小机器上)。

有些系统是弹性的,这意味着可以在检测到负载增加时自动增加计算子资源,而其他系统则是手动扩展。

1.3.可维护性

什么是可维护性?

工程师和运维在不同的生命周期,都能高效的在系统上工作。

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

软件在设计之初,就尽量考虑可能减少维护期间的痛苦,从而避免自己的软件系统变成遗留系统,为此,我们将特别关注软件系统的三个设计原则:

  • 可操作性

    便于运维团队保持系统平稳运行。
  • 简单性

    从系统中消除尽可能多的复杂度,使新工程师也能轻松理解系统。
  • 可演化性

    使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配,也称为可扩展性,可修改性,或可塑性。

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

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

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

1.3.2.简单性:管理复杂度

一个陷入复杂泥潭的软件项目有时被描述为烂泥谭

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

简化系统并不一定以为着减少功能:它也可以意味着消除额外的复杂度。

额外的复杂度指:在具体实现中出现,而非(从用户视角看,系统所解决的)问题本身固有的复杂度。

用于消除额外复杂度的最好工具之一是抽象。一个好的抽象可以将大量实现细节影藏在一个干净,简单易懂的外观下面。

1.3.3.可演化性:拥抱变化

系统的需求永远不变,基本是不可能的,更真实的是一直处于常态的变化中。

在组织流程上,敏捷工作模式就是为了适应变化提供的一个框架。

在数据系统层面的敏捷性使用可演化性来替代。

相关推荐