DDIA读书笔记第一章——可靠性、可扩展性、可维护性

现今大多数系统是数据密集型系统,而非计算密集型,所以CPU一般很少成为这类系统的瓶颈,数据量、数据复杂性、数据的变更速度往往是这类系统更关心的问题。
许多数据密集型系统都需要依赖通用组件,比如:

  1. 存储数据,以便以后能够再次读取(数据库database)
  2. 保存一些高昂开销的操作结果,以便以后能够快速访问(缓存cache)
  3. 允许用户对存储的数据按照关键词搜索,同时可以按照某种方式过滤(搜索引擎search index)
  4. 向其他进程发送消息,进行异步处理(流处理stream processing)
  5. 定期处理累计的大批量数据(批处理batch processiong)

关于数据系统的思考

不同种类的系统,比如数据库、消息队列、缓存,从作用上说,差异很大,但是实际上很多功能都是重合的,所以把他们统一归类为数据系统。
一个可能的应用如下,将多个工具组合起来,最终对外给用户提供服务
DDIA读书笔记第一章——可靠性、可扩展性、可维护性_第1张图片
设计数据系统或服务时可能会遇到很多棘手的问题,例如:当系统出问题时,如何确保数据的正确性和完整性?当部分系统退化降级时,如何为客户提供始终如一的良好性能?当负载增加时,如何扩容应对?什么样的API才是好的API?
​ 影响数据系统设计的因素很多,包括参与人员的技能和经验、历史遗留问题、系统路径依赖、交付时限、公司的风险容忍度、监管约束等,这些因素都需要具体问题具体分析。
​ 本节着重讨论三个在大多数软件系统中都很重要的问题:
1、可靠性(Reliability):系统在困境(adversity)(硬件故障、软件故障、人为错误)中仍可正常工作(正确完成功能,并能达到期望的性能水准)。
2、可扩展性(Scalability):有合理的办法应对系统的增长(数据量、流量、复杂性)
3、可维护性(Maintainability):许多不同的人(工程师、运维)在不同的生命周期,都能高效地在系统上工作(使系统保持现有行为,并适应新的应用场景)

可靠性

可靠性指即使出现问题,系统仍能对外提供正确的服务,具体可以有以下方面:
1、允许用户已错误的方式使用系统
2、系统内存发生错误时,比如硬件错误、运维错误等,仍能对外提供服务
3、在预期的负载和数据量下,系统能够正确工作
4、系统能防止未经授权的访问和滥用
故障是没办法阻止的,所以一般数据系统都会设计容错机制。

硬件故障

磁盘、内存、断电、网络都有可能出现故障,例如,磁盘的平均无故障时间约为10~50年,只要集群规模大,发生硬件故障的次数就多。
为了减少系统的故障率,通常是增加单个硬件的冗余度,例如:磁盘可以组建RAID,服务器可能有双路电源和热插拔CPU,数据中心可能有电池和柴油发电机作为后备电源,某个组件挂掉时冗余组件可以立刻接管。
我们设计数据系统时,更多考虑容错性和弹性,而不是单机可靠性

软件错误

软件错误比硬件故障更能造成系统不可用

人为错误

运维操作造成的系统中断比例很高

可靠性有多重要

可靠性无疑是数据密集型系统中最重要的

可扩展性

可扩展性与系统负载有关

描述负载

负载与特定系统有关,用户请求qps、在线用户数量、磁盘io等等

描述性能

从两个方面看待负载和性能的关系:
1、负载增加,系统资源(CPU、内存、网络带宽)不变时,系统性能会下降多少
2、负载增加,要想保持性能不变,需要增加多少系统资源
不同系统关注的性能指标不同,比如批处理系统,关注吞吐量,在线系统,关注时延。
对于时延,可以关注平均值、tp95、tp99、tp999、最大值,对于服务用户的系统,多关注百分点指标。
排队延迟通常占了高百分位点处响应时间的很大一部分,由于服务器只能并行处理少量的事务(如受其CPU核数的限制),所以只要有少量缓慢的请求就能阻碍后续请求的处理,这种效应有时被称为头部阻塞,即使后续请求在服务器上处理的非常迅速,由于需要等待先前请求完成,客户端最终看到的是缓慢的总体响应时间,因为存在这种效应,测量客户端的响应时间非常重要。
为测试系统的可扩展性而人为产生负载时,产生负载的客户端要独立于响应时间不断发送请求。如果客户端在发送下一个请求之前等待先前的请求完成,这种行为会产生人为排队的效果,使得测试时的队列比现实情况更短,使测量结果产生偏差。

应对负载的方法

横向扩展和纵向扩展,一般系统倾向于横向扩展,但是有时间用几台高性能机器比多个小型虚拟机更简单也更便宜,需要综合考虑。对于无状态服务多台部署很简单,但是将有状态服务从单节点变成分布式很困难,所以一般数据库单机部署,直到扩展成本或可用性需求迫使其改为分布式。
大规模的系统架构通常是应用特定的—— 没有一招鲜吃遍天的通用可扩展架构,应用的问题可能是读取量、写入量、要存储的数据量、数据的复杂度、响应时间要求、访问模式或者所有问题的大杂烩,一个良好适配应用的可扩展架构,是围绕着假设(assumption)建立的:哪些操作是常见的?哪些操作是罕见的?这就是所谓负载参数。如果假设最终是错误的,那么为扩展所做的工程投入就白费了,最糟糕的是适得其反。

可维护性

众所周知,软件的大部分开销并不在最初的开发阶段,而是在持续的维护阶段,包括修复漏洞、保持系统正常运行、调查失效、适配新的平台、为新的场景进行修改、偿还技术债、添加新的功能等等。
但是我们可以,也应该以这样一种方式来设计软件:在设计之初就尽量考虑尽可能减少维护期间的痛苦,从而避免自己的软件系统变成遗留系统。为此,我们将特别关注软件系统的三个设计原则:
1、可操作性(Operability):便于运维团队保持系统平稳运行。
2、简单性(Simplicity):从系统中消除尽可能多的复杂度(complexity),使新工程师也能轻松理解系统。(注意这和用户接口的简单性不一样。)
3、可演化性(evolability):使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配。也称为可扩展性(extensibility),可修改性(modifiability)或可塑性(plasticity)

本章小结

你可能感兴趣的:(DDIA读书笔记,数据库,分布式)