本系列为《Designing Data-Intensive Application》的读书笔记加总结系列,至于DDIA是一本什么样的书我这里可以做一个简单介绍,DDIA是一个偏向分布式系统设计的,书中讲解一些分布式系统中一些话题,更偏向的大规模数据系统容易遇到的问题。算是有经验的开发者对普通开发者传授这方面的知识的书籍吧,书有大量的案例来讲解实际分布式系统设计所面临的问题和挑战,并且给出了各种不同解决方案的优劣性,至于内容有没有营养这个因人而异。


何为数据系统?

什么是数据系统?在大多数开发者认为的是数据库这种系统才是数据系统,但是书中给出的解释是涉及到数据操作的都可以算是数据系统。日常开发使用的数据库、Redis、消息队列、全文搜索引擎等,这些都是有相似之处都是和数据打交道,而今天一个大型的项目都会使用很多组件来构建而成的。每个组件有自己的独特功能,但是又是相互紧密连接在一起工作的,所以一个大型数据系统架构就是在这种环境下形成的。

因为是不同的组件,所以单机肯定是不能满足去构建一个系统的,这时就会通过网络分布式形式组成一个庞大系统,但是此时就会带来很多问题,例如:数据一致性、数据完整性、当某组件出现故障时是不是能快速恢复,如何面对随着用户数量的增长系统负载的问题等等...


数据系统设计

本篇为分布式系统设计要考虑的Reliability, Scalability, Maintainability的内容整理和笔记总结;一个应用系统前置设计要考虑的问题,当今一个系统都是围绕着数据的,但是万变不离其宗,一个系统变大了之后下面这些是必须会出现的:

组件作用用途
数据库数据库就不用说了,稍微像样一点的应用都会有
内存缓存内存速度很快价格很贵,但是可以提升程序性能
流式系统可以将一些任务异步处理,放到另外一个独立的程序中
批处理可以定时做某些任务,批量处理大量累积的数据

书中第一章部分作者对现在大部分开发者评价是说,现在的开发者大多数只是会使用别人已经写好的软件去组装成一个大规模数据处理系统,而对这些组件本身底层实现缺乏一定的认识,像我们这种都是拿来即用主义的。而现在很多开源的轮子可以供开发者选择了,例如现在NoSQL这么多,你怎么去做选择,或者说其中哪一款适合你的业务场景?但是开发者如何选择?怎么选择?却成为一个问题?并且怎么去用这些组件像玩乐高一样搭建出来一个健壮的系统?

影响一个数据系统的设计因素有很多,其中包括相关的技术人员的技能和经验水平,系统遗留的依赖问题、交付周期、对不同环境风险监测和监管,还有系统故障的容错性等。所以在一个系统设计的时候要考虑的最重要的3个因素是:可靠性、可扩展性、可维护性,这时书中第一章介绍的,下面开始是我对这些部分读书笔记总结和归纳。


可靠性

什么是可靠性?可靠性这里我再没有阅读这本书之前认为的是软件容错性,在软件出错的时候还能保证系统正常而不是整个宕机。但是在阅读之后作者给出了影响一个系统的可靠性因素有很多,例如:

  • 软件问题
  • 硬件问题
  • 人员问题

这些都是影响一个大型项目可靠性的因素,可靠性书中提出观点是:程序能执行用户期望的效果,可以允许部分组件出错不影响整体系统,系统可以禁止一下未经授权访问的滥用。总体还是说就是要保证系统的高可用性,在系统部分程序出现问题的时候,系统还能正常运作,而不是失效直接宕机,失效(failure)不等于故障。

软件问题可能是编写程序的时候写出的Bug,这些bug在正常情况下是不会出现的,只要某些特定的条件下才能触发的bug,针对这种问题在编写的程序的时候要加强代码的可测试性和代码测试覆盖率。例如使用消息队列的时候输入的消息数据和输出的消息数量应该是成正比;级联故障其中一个组件出错不应该影响到另外一个组件从而蔓延到整个系统导致整个系统无响应。

硬件故障是一个大型的系统必然出现的问题,例如分布式文件存储系统,由于有大量的数据文件要存储,就需要很多硬盘做为存储数据的容器,但是文件系统是频繁读写导致硬盘容易出现问题。有一些研究表明一个正常数据中心平均无故障时间MTTF约10~50年,因此10_000个硬盘存储集群中平均每天都会发生磁盘故障;这样的问题在Hadoop系统中采用的冗余备份,多副本写入,还有一些就是滚动升级,逐步停机维护组件,而不是停止整个系统。

人为失误大型系统大部分多个团队来一起完成的,系统设计也是多方面的人员加入,这时就带来一个新的问题就是怎么保证这些人经验是合格的,操作是合规的;有关统计也是表明大部分软件问题是人为操作失误造成的,真正的硬件故障还不到百分之25。假设人是不可靠的,那该怎么保证系统可靠性?以最小的出错方式来设计系统,设计好的API接口使其调用者能正常的传入需要的数据,想办法把容易出错的地方单独拿出来隔离,加强对人员的相关知识培训工作。如果真的在运行过程中出错了最后能及时发现并且能快速处理,有回滚代码功能的管理流程,提供一些方便运维的工具。

软件可靠性可以影响一个公司正常运作,也能影响到一个公司财产。往大的说空中交管软件可能会影响到人的生命,例如最近的波音737MAX型号的客机传感器问题,例如核电站的切尔洛贝利核电站人员操作失误导致的问题,这些都是要在系统设计的考虑到的,来保证一个大型系统可靠性。


可扩展性

一个系统在初期的时候可能因为流量和用户量比较少,当时设计的架构可能会满足这方面的要求,但是随着时间的增长用户也会随着时间变化,系统现在是可靠并不意味着它未来是可靠的,未来面临的数据负载可能会指数级上涨,这就给你系统设计人员带来扩展性问题,该如何面对某种方式的增长的措施有哪些?如果是web应用程序负载可能是指每秒钟处理请求的数量,而对于数据库更关注的是读写比例,聊天室关注的的是同一时刻用户在线人数,缓存系统更关注的是命中率,流式批处理系统更关注的是系统吞吐量。

程序扩展问题是为了解决程序负载问题,负载增加时将会发生什么?如果负载量增加了,但是系统的资源CPU、内存、网络带宽保持不变的话,会带来什么的影响?负载量增加,系统资源如何增加?

web服务器关注的是一个请求从客户端到服务器到处理完成返回的时间,而这其中还有在网络链路上传输的时间,前者是响应时间、后者是延迟时间;影响响应时间因素很多,例如处理数据量太大,处理线程发生上下文切换、有GC的编程语言需要STW收集垃圾,缺页异常换页操作磁盘IO等;而网络时间延迟这个得看网络线路问题导致,数据中心一般可以配置多个网络线路。

日常计数一个平均值都是将其累加起来然后除以请求个数,这样算法在书中作者表示不够准确。而作者给出一种方法就是把请求响应时间从小到大排序,然后取一个中间值来分段评测,如果左边的请求数量比右边的多,说明请求延迟是合理的,否则相反就要去考虑对系统进行调整优化或者扩展了,这里我对此部分内容还是比较生疏,可以查看原文:实践中的百分位点

尾部效应对应着就是上面说的P95百分位的请求响应时间的后面部分请求,这些请求往往比前面的请求慢,例如上图一个后端服务有多个服务组成,一个请求可能需要多个的服务提供,但是请求响应时间依赖于最长的那个服务,这时就要考虑引入算法了解决这些问题了。如果百分之5的慢响应落到了VIP用户身上就会影响到用户体验,一般用户不会等待很久而是离你而去,所以大部分系统设计处理请求响应时间的时候要考虑到这个问题,减低尾巴效应。

这里解决问题就是将响应数据长的服务器要么垂直扩展,就是给机器堆硬件,这种是针对硬件的弊端就是硬件添加上去了,可能请求是临时负载增高,后面可能用不到这么强的硬件设备;而另外一种就是软件的方式水平扩展,水平扩展可以将服务拆分成小的服务部署到多个服务器(VPS)上运行,可以动态调整服务数量,后面这种方案是可行的。如果是水平扩展就会引入很多分布式问题,因为水平扩展属于无共享体系架构,如果是这样就会出现很多分布式系统设计问题,这些问题也是本书中作者所要讨论的问题。


可维护性

软件开发并不意味着只是在开发阶段或者设计阶段投入人力物力资源,特别是大规模的服务端软件是要不停迭代和运维的,定期修复一些问题来保证整个系统的可靠性;也有一部分开发者需要去接手一些历史依赖软件项目,这时也要充当系统运维的角色,有时候在维护一个别人的老系统的时候可能会想代码怎么会写成这个样子?如果换成你在早期开发阶段会不会考虑到这些问题呢?如果在设计的时候和开发阶段有良好的工程质量保障的话,可以完全避免一些在后面出现的一些需要运维的问题,尽可能减少后期投入的运维成本,避免系统出错,也可以考虑设计一个方便运维的管理流程。

在书中作者可维护性可以分为3个要素:

可运维性: 如果一个项目连最基本的可运维性都没有可以说是一个乱项目,可运维就是项目上线之后能跟踪软件运行状态有专门的团队运营,项目也有很好工具文档提供,避免后面有新的成员加入能快速理解整个项目,不要把软件和特定的硬件绑定到一起,这样就让软件非常依赖环境因素。

简单性: 项目代码和各个代码层次要保持简单,这里的简单不是说减少功能,而是设计好的抽象层和易懂的接口,例如完全没有必要用低级语言地方就不要使用,因为低级语言更接近底层但是未必所有的开发者能掌握好这些技能,可以使用一些已经被广泛使用的框架和高级语言,例如Java软件生态有很多成功的开源软件,也有很多编程范式和语言相关的规范。

可演变性: 敏捷开发是现在最常见的开发模式,软件可能因为环境的变化就要变化,监管法律和项目需求的变化,可以看看现在一些软件工程方面流行的开发模式,例如TDD;不要把系统代码编写的很复杂,这样在更改的时候会出现很多问题,提供好易扩展API接口,由于代码有很多不同的人编写的所以会出现不同情况,这时就要去定制一些关于的项目的规范了,也可以使用一些通用的工具去解决。


上面为全书的第一章部分,作者介绍很多关于一个大型系统设计开发面临各种问题,并且提出了上面这些大型系统在项目启动初期要考虑到的问题,每个系统都有自己对应独特需求的,没有一套完整的方案,但是都会考虑上面所说的要素。对应一个创业公司产品没有定性,更关注的是后面可扩展性和维护性,对应一个超大型项目可靠性和运维性很重要。

便宜 VPS vultr
最后修改:2023 年 07 月 05 日
如果觉得我的文章对你有用,请随意赞赏 🌹 谢谢 !