第一部分:适用于所有数据系统的基本思想

第1章:术语与方法

  • 数据库
  • 高速缓存
  • 索引:按关键字搜索数据并支持各种过滤
  • 流式处理:持续发送消息至另一个进程,处理采用异步方式
  • 批处理:定期处理大量的累积数据

设计数据系统时会遇到的问题

  • 当系统内出现了局部失效时,如何确保数据的正确性与完整性?
  • 当发生系统降级时,该如何为客户提供一致的良好表现?
  • 负载增加时,系统如何扩展?
  • 友好的服务API该如何设计?

目标

可靠性

硬件错误、软件错误、人为错误

可扩展性

本系统的负载是什么?(每秒请求处理次数?同时活动用户数量?平均值?峰值?)

负载增加但系统资源不变,系统性能会发生什么变化?

负载增加,如果要保持性能不变,需要增加多少资源?

本系统的性能指标如何衡量?(吞吐量?响应时间?)

负载增加时,如何保持良好的性能?(垂直拓展:升级到更强大的机器。水平拓展:将负载分布到多个更小的机器,无共享体系结构)

弹性拓展:自动检测负载增加,自动添加更多计算资源

手动拓展:人工分析性能表现,手动添加更多计算资源

无状态服务水平拓展比有状态服务更容易。

超大规模的系统要针对应用定制,没有一套通用的框架,所以说这种架构师的岗位是无法替代的,有出路,可以一直搞,从通用的组件定制出一个超大规模的系统。

可维护性

运维简单、项目复杂度低、易于改变

第2章:数据模型与查询语言

每层通过提供一个简洁的数据模型来隐藏下层的复杂性。

数据模型

层次模型:

不好用,基本用下面三种

关系模型:

写时模式(写时强制)

劣势:对象-关系不匹配(阻抗失谐,需要一个转换层也就是ORM)

文档模型:

读时模式(读时处理)

图模型

读时模式(读时处理)

所有数据都有可能相互关联

一个模型可以用另一个模型来模拟,但是在不同场景下,有的模型过于笨重,所以不同的系统用于不同的目的。

还有其他的模型(全文索引等)

查询语句

命令式

告诉计算机以特定的顺序执行某些操作,指定如何实现

声明式

只需指定所需的数据模式,不需要指定如何实现,系统自动选择

MapReduce

编程模型

查询的逻辑用代码片段来表示,这些代码片段可以被处理框架重复地调用。

基于函数语言中的map(也称collect)和reduce(也称fold或inject)函数

第3章:存储引擎

日志:表示一个仅能追加的记录序列集合。

墓碑:表示这个记录被删除的标记

索引结构

哈希索引:

必须全放进内存(放到磁盘基本没用)

不能简单支持区间查找

存储段key-value对不需要有序

值可以是实际行(文档,顶点),也可以是对其他地方存储的行的引用(这个用的多,因为存在多个二级索引的时候就可以避免复制数据),存储具体行的文件叫堆文件,

聚集索引:

在索引文件中保存行数据

非聚集索引:

索引文件中只存储数据的引用

覆盖索引:

多列索引:

全文索引和模糊索引:

日志结构

SSTable(排序字符串表)

key-value对有序

LSM存储引擎

Log-Structured Merge-Tree

性能优化

布隆过滤器

分层压缩(LevelDB,RocksDB)

大小分级(HBase)

B-trees

B-Tree的操作复杂,所以中途崩溃会导致操作无法完成,而且可能会破坏索引(比如分裂页中途崩溃)

使用日志做保障

内存数据库的性能优势不是因为它们不需要从磁盘读取,而是避免了写磁盘格式对内存数据结构编码的开销。

在线事务处理(online transaction processing)OLTP

在线分析处理(onlien analytic processing)OLAP

将数据库导入数据仓库的过程称为提取-转换-加载(Extract-Transform-Load,ETL)

数据仓库

星形表与雪花表

星形表:数据存储在一张巨大的事实表中,其他的表由它发散出去

雪花表:通过外键连接彼此

列式存储

可以使用位图进行列压缩

第4章:数据编码格式与序列化技术

第二部分:分布式场景下的典型问题和解决方案。