数据密集型应用系统设计-笔记(一)
记录在阅读《数据密集型应用》一书过程中的笔记和疑惑心得,以备后用;
数据系统基础
第一部分主要讲述的是数据系统基础部分,主要介绍数据系统特点、数据模型、数据操作这几个方面;
数据系统特点
数据密集型应用和计算密集型应用最大的区别是在于CPU是否是瓶颈,数据密集型应用的关键是在于数据量、数据的复杂度及数据的快速多变性上;
与数据密集型应用有关的模块(组件)通常有:
- 数据库:用以持久化数据
- 高速缓存:缓存哪些复杂或者操作代价昂贵的结果,以便下次快速进行访问
- 索引:加快搜索效率
- 流式处理:持续发送数据的一种方式
- 批处理:定期处理大量数据
一个应用系统往往是由多个数据组件共同协作,应用系统将任务进行拆解,每一个组件高效完成其中一部分功能,多个组件依靠应用层代码驱动衔接;
影响系统设计的三个重要因素
可靠性、可扩展性、可维护性
- 可靠性
可靠性在软件领域通常可以指的是执行结果是否如期望所示、是否可以容忍错误的使用方法、性能上是否可以应对合理的负载压力、禁止未经授权的访问等等;
可能出错的事情称为故障或错误,系统可应对错误则称为容错或弹性;故障和失效是不完全一致的,故障通常被定义为组件偏离其正常规格,而失效意味着系统作为一个整体的停止,无法提供服务的状态;
因此通常需要设计容错机制来避免由故障引发系统失效的场景;
- 可扩展性
可扩展性是用来描述系统在应对负载增加能力的术语
软件系统中的可扩展性指的是,当负载以某种方式增加时,合理的应对策略;因为每个系统的所面对的负载增长都是不相同的,因此需要不尽相同且合理的应对策略来解决;
- 可维护性
软件的大部分成本并不是在最初的开发阶段投入的,而是在整个生命周期内持续不断的投入,由于初始开发阶段会决定整体软件的底层架构,底层架构设计是决定系统可维护性最重要的因素,因此在软件的初始阶段就要考虑三个设计:可运维性<B>简单性\可演化性等
- 可运维性
方便运营团队来保持系统平稳运行 - 简单性
简化系统复杂性,使新的工程师能够轻松理解系统; - 可演化性
后续工程师能够轻松的对系统进行改进,并根据需求变化将其适配到非典型场景中;
在业务主导的环境中能同时做好这3点,并不容易,但是如果系统需要长期进行维护5年以上,这些是值得进行投入的;
数据模型与查询语言
第二部分主要介绍了各种不同的数据模型,分别是文档模型、关系模型、图模型
数据模可能是开发软件最重要的部分,它们不仅对软件的编写方式,而且还对如何思考待解决的问题都有深远的影响;
软件系统中数据模型为什么可以影响思考和处理需求的方式?
Martin Kleppmann 指出一个深刻的见解:数据模型不仅是关于如何存储数据,它更是关于我们如何看待问题的“思维框架”。数据模型之所以能影响思考和处理需求的方式,核心原因在于它设定了抽象的边界
数据模型就是软件的底层基因,决定了:
- 认知方式:把数据看作一张表、一棵树还是一张网
- 解决路径:是使用关系型模型解决还是使用嵌套文档解决
- 约束条件:模型能支持多大的并发量,是否能支持复杂的关联查询等;
正如书中名言所说:“应用程序的开发者通过观察现实世界,将其建模为对象、数据库表以及处理这些数据的 API。这些抽象简化了我们的工作,但也决定了我们处理问题的天花板。”
数据存储与检索
索引是基于原始数据派生而来的额外数据结构,很多数据库允许单独添加和删除索引,而不影响数据库的内容,它只会影响查询性能;
适当的索引可以加速读取查询,但每个索引都会减慢写入的速度;
索引的结构可以分为哈希索引、SSTables
SSTables实现上有LSM-Tree这种实现,通过写日志的方式将数据进行写入后在组织索引;
数据仓库
数据仓库是单独的数据库,分析人员可以在不影响OLTP操作的情况下尽情的使用.数据仓库包含公司所有各种OLTP系统的只读副本.从OLTP数据库中提取数据,转换为分析友好的模式,执行必要的清理,然后加载到数据仓库中.将数据导入数据仓库的过程称为提取-转换-加载(ETL)
数据仓库的结构通常有两种:星型结构和列式存储

星型结构是通过用事实表去关联属性表来完成建模;
列式存储是将每一列中的所有值都存储在一起,如果每个列存储在一个单独的文件中,查询只需要分析在本次查询中使用到哪些列;
数据编码与演化
数据格式以及这些格式如何影响系统的演进能力,数据格式必须要有向前兼容和向后兼容的能力;
为什么我们不能只用JSON? 作者通过分析发现,当你进入大规模分布式系统时,模式(Schema)的价值就体现出来了:
更紧凑: 二进制编码体积更小。
更安全: 模式充当了文档和契约。
更健壮: 在代码部署阶段(灰度发布),它能保证系统不会因为无法解析数据而崩溃。