第1章 可靠性,可扩展性,可维护性
第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.可演化性:拥抱变化
系统的需求永远不变,基本是不可能的,更真实的是一直处于常态的变化中。
在组织流程上,敏捷工作模式就是为了适应变化提供的一个框架。
在数据系统层面的敏捷性使用可演化性来替代。