全书术语
全书反复用到的术语,每个只在这里讲一次,章节页链过来。按第一次出现的章排,同一章里按出现顺序。每条给英文、本站的中文译法和本站自己写的解释(不是原书词汇表的翻译);末尾的链接回到第一次讲它的那一章。译本的译法可能和这里不同,按英文对。
第 1 章起
OLTP (online transaction processing)在线事务处理
按键取出少量记录,按用户的操作逐条增删改。查询是写在应用代码里的固定几种,每次只碰几行,要求延迟低。
第一次出现:第 1 章 §1.1
OLAP / analytics联机分析处理 / 分析
一次扫过大量记录,算计数、求和、平均这类汇总,不返回单条记录。查询多是分析师临时写的,数据集从 TB 到 PB 级。
第一次出现:第 1 章 §1.1
data warehouse数据仓库
一个单独的数据库,存公司各个业务系统数据的只读副本,专门给分析用。分析师在这里怎么查都不影响线上业务,存储方式也按分析查询优化。
第一次出现:第 1 章 §1.2
ETL / ELT (extract–transform–load)抽取、转换、加载
把数据从业务库抽出来,转换成适合分析的模式并清洗,再加载进数据仓库。先加载、在仓库里再转换的叫 ELT。后来推广为更一般的数据管道。
第一次出现:第 1 章 §1.2
system of record (source of truth)记录系统(事实来源)
数据第一次写入的地方,存权威的那一份,每个事实只记一次。别的系统和它对不上时,以它为准。是不是记录系统取决于在应用里怎么用,不取决于用的是哪种数据库。
第一次出现:第 1 章 §1.3
GDPR (General Data Protection Regulation)《通用数据保护条例》
欧盟的数据保护法规,2018 年起适用。书里多处提到它:被遗忘权给不可变日志和 LSM 树带来的删除难题,以及第 14 章引的同意、目的限定和数据最小化条文。
第一次出现:第 1 章 §4
第 2 章起
percentile百分位数
把响应时间从快到慢排好,排在某个位置上的值。p50 即中位数,p99 表示一百个请求里只有一个比它慢。几台机器的百分位不能取平均,要合并直方图再算。
第一次出现:第 2 章 §2.2
第 3 章起
declarative query language声明式查询语言
只说要什么样的结果(条件、排序、分组),不说怎么算;用哪个索引、按什么顺序连接、要不要并行,由数据库的查询优化器决定。所以数据库改进了执行方式,查询不用改。
第一次出现:第 3 章 §0
normalization / denormalization规范化 / 反规范化
给人看的信息只存一处,别处用一个不会变的 ID 引用,叫规范化;把信息抄进每条用到它的记录,叫反规范化。前者写便宜、读时要连接,后者读快、写时要更新所有副本。
第一次出现:第 3 章 §1.2
schema-on-read / schema-on-write读时模式 / 写时模式
数据库不检查数据结构,由读数据的代码假定并解释结构,叫读时模式;数据库在写入时保证数据符合显式的模式,叫写时模式。书里拿它类比动态和静态类型检查。
第一次出现:第 3 章 §1.5
event sourcing事件溯源
把每一次状态变化记成一条不可变、用过去时命名的事件,追加到日志里,日志是唯一的事实来源;读用从日志派生的物化视图。把写的表示和读的表示分开的原则叫 CQRS。
第一次出现:第 3 章 §3
第 4 章起
log日志
只能往末尾追加的一串记录。书里说的日志不是程序打印给人看的那种,而是数据库内部的数据结构:预写日志、LSM 树的段、复制日志、消息队列,都是它。全书反复回到这个结构,因为追加写最快、最容易在崩溃后恢复,也最容易被别人按顺序读走。
第一次出现:第 4 章 §1
LSM-treeLSM 树(日志结构合并树)
一类存储引擎:写先进内存里的有序表,满了整个写成不可变的有序文件(段),后台不断把段合并,丢掉旧值和已删除的值。写入是成片的顺序写,适合写多的负载;读可能要查好几个段,靠布隆过滤器少读一些。
第一次出现:第 4 章 §1.1
compaction合并(压实)
在后台把几个文件合成一个新文件,同一个键只留最新的值,删掉的值和墓碑一起扔掉。LSM 树靠它回收空间、减少读时要查的文件数;代价是要占磁盘带宽,写入太快时可能跟不上。
第一次出现:第 4 章 §1.1
B-treeB 树
把磁盘分成固定大小的页,页里存一串有序的键和指向下层页的页号,组成一棵很矮的平衡树。改数据就覆盖写那一页;页满了就分裂。几乎所有关系数据库都用它做索引,读的性能稳定。
第一次出现:第 4 章 §1.2
write-ahead log (WAL)预写日志
改数据之前,先把「要改什么」追加写进一个日志并刷到盘上,然后才去改真正的数据结构。崩溃后按日志重做,就能回到一致的状态。B 树用它防页分裂改到一半;后面几章的复制、事务也会用到它。
第一次出现:第 4 章 §1.2
write amplification写放大
一次应用层的写,在磁盘上变成了好几次写:日志一次、数据页或段一次、每次合并再一次。用实际写盘的字节数除以「只追加、不建索引」要写的字节数来衡量。写放大越高,同样的磁盘带宽能扛的写越少,SSD 也磨损得越快。
第一次出现:第 4 章 §1.3
column-oriented storage列式存储
把一张表每一列的值存在一起,而不是把每一行的值存在一起。分析查询通常只用几列、却要扫很多行,列存只读需要的列,同一列的值又很好压缩。各列靠「第 k 个值属于第 k 行」对上。
第一次出现:第 4 章 §2.2
第 5 章起
schema evolution模式演化
模式随时间改变(加字段、删字段、改名、改类型),同时保持向后和向前兼容。Protocol Buffers 靠标签号的规矩做到,Avro 靠写者模式、读者模式和默认值做到。
第一次出现:第 5 章 §1.3
remote procedure call (RPC)远程过程调用
想让一次网络请求看起来和调用本地函数一样。网络请求会超时、会重复、延迟忽高忽低,所以作者认为这种「位置透明」的抽象有根本缺陷。
第一次出现:第 5 章 §2.2
第 6 章起
failover故障切换
主库坏了,把一个从库提升为新主库,再让客户端和其他从库改认它。分三步:判定主库死亡(通常靠超时)、选新主库、重新配置。超时太长恢复慢,太短会误切换。
第一次出现:第 6 章 §1.3
read-after-write (read-your-writes) consistency读己之写一致性
用户总能读到自己提交过的改动,对别人的改动不作承诺。常见实现:可能被自己改过的数据从主库读;或者记住自己最后一次写的位置,只读已经追上这个位置的副本。
第一次出现:第 6 章 §1.5
last write wins (LWW)最后写入者胜
冲突时留下时间戳最大的值,其余悄悄丢掉。并发的写本来就没有先后,所以实际上等于随机挑一个;用实时时钟时还会被时钟偏差影响。
第一次出现:第 6 章 §2.3
conflict-free replicated datatype (CRDT)无冲突复制数据类型
能把并发修改自动合并的数据结构,各副本处理过同一组写之后,不管到达顺序如何都收敛到同一状态。文本、列表、计数器、键值映射都有对应的实现。
第一次出现:第 6 章 §2.3
quorum法定人数
读和写各要多少个副本回应才算成功。n 个副本、写等 w 个、读等 r 个,w + r > n 时读和写的集合至少重叠一个副本。不一定非得是多数。
第一次出现:第 6 章 §3.1
version vector版本向量
每个副本一个版本号,合在一起用来判断两次写是先后关系还是并发。读的时候发给客户端,写的时候带回来。和向量时钟(vector clock)相近,但不完全一样。
第一次出现:第 6 章 §3.4
第 7 章起
shard / partition分片(分区)
数据切出来的一块,每条记录只属于一个分片,每个分片放在一台或几台机器上。分片通常和复制一起用:一条记录只属于一个分片,但这个分片可以有好几份副本。各系统叫法不同(partition、range、region、tablet、vnode……)。
第一次出现:第 7 章 §0
skew / hot spot倾斜 / 热点
有的分片数据或请求远多于其他分片,叫倾斜;负载特别高的那个分片叫热点。单个键特别热的叫热键,换哪种分片方案都只落在一个分片上。
第一次出现:第 7 章 §3
consistent hashing一致性哈希
一类把键映射到分片的算法:各分片分到的键大致一样多,分片数变化时只搬最少的键。这里的「一致」和副本一致性、ACID 的一致性都没有关系。
第一次出现:第 7 章 §3.2
第 8 章起
ACIDACID
原子性、一致性、隔离性、持久性的缩写,描述事务的安全保证。原子性指出错时整个中止,一致性指应用定义的不变式;各家实现差别大,作者说它如今多半是营销用语。
第一次出现:第 8 章 §1.1
snapshot isolation快照隔离
每个事务从开始那一刻的一致快照里读,看不到之后别人提交的写;通常用多版本实现,读不挡写、写不挡读。挡得住读偏斜,挡不住写偏斜。
第一次出现:第 8 章 §2.2
multiversion concurrency control (MVCC)多版本并发控制
一行同时保留几个版本,每个版本标着创建和删除它的事务号,读的事务按可见性规则挑自己该看的那个。快照隔离最常见的实现。
第一次出现:第 8 章 §2.2
serializability可串行化
最强的隔离级别:并发执行的结果和某种一个接一个执行的结果相同,因而防得住所有竞争。实现有真串行执行、两阶段锁、SSI 三种。和线性一致性不是一回事。
第一次出现:第 8 章 §3
two-phase locking (2PL)两阶段锁
读拿共享锁、写拿排他锁、锁一直持有到事务结束的可串行化实现,用谓词锁或索引范围锁防幻读。读写互相阻塞,延迟不稳定。别和两阶段提交混淆。
第一次出现:第 8 章 §3.2
serializable snapshot isolation (SSI)可串行化快照隔离
在快照隔离上加冲突检测的乐观算法:事务照常执行、不因冲突等待,提交时如果发现自己读到的前提已被别人提交的写改掉,就中止。只读事务不受影响。
第一次出现:第 8 章 §3.3
two-phase commit (2PC)两阶段提交
让多个节点对一个事务要么都提交、要么都中止的协议:协调者先问所有参与者能否提交,全部答「是」才把提交的决定写进日志再通知大家。协调者崩溃时,答过「是」的参与者只能持锁等待。
第一次出现:第 8 章 §4.1
第 9 章起
partial failure部分失效
系统的一部分坏了,其余照常工作,而且常常说不清坏没坏、坏在哪。单机被设计成「要么好、要么全坏」,分布式系统做不到这一点,只能在软件里去容忍。
第一次出现:第 9 章 §1
system model系统模型
把算法对网络延迟、进程停顿、时钟误差和节点故障的假设写下来。时间方面有同步、部分同步、异步,故障方面有崩溃-停止、崩溃-恢复、拜占庭等。
第一次出现:第 9 章 §4.4
safety / liveness安全性 / 活性
两类正确性质。安全性是「坏事不发生」,一旦违反能指出是哪一刻、无法挽回;活性是「好事终会发生」,此刻没做到将来还有希望。
第一次出现:第 9 章 §4.4
第 10 章起
linearizability线性一致性
多副本对外表现得像只有一份数据。每个操作在请求发出到收到响应之间的某一刻原子地生效;一旦有人读到新值,此后开始的读都不能再读到旧值。它只管单个对象,和管事务的可串行化是两回事。
第一次出现:第 10 章 §1
Lamport timestampLamport 时间戳
写成(计数, 节点 ID)。每产生一个时间戳计数加一,看到更大的计数就把自己的抬上去。它给出一个和因果一致的全序,但分不出两个事件是否并发,也不保证线性一致。
第一次出现:第 10 章 §2.1
hybrid logical clock混合逻辑时钟
计数按物理时间走,又像 Lamport 时钟那样看到更大的时间戳就跟着往前拨。它的时间戳近似挂钟时间,顺序又和因果一致;书里举的例子是 CockroachDB。
第一次出现:第 10 章 §2.1
shared log / total order broadcast共享日志 / 全序广播
多个节点都能请求追加条目,所有节点按同一顺序读到这些条目。它和共识等价,多数共识系统提供的就是它。
第一次出现:第 10 章 §3.1
epoch number任期号
每次选主时递增的编号,Paxos 叫 ballot number,Raft 叫 term。共识算法只保证同一个任期里最多一个主,任期号大的主说了算。
第一次出现:第 10 章 §3.2
coordination service协调服务
ZooKeeper、etcd、Consul 这一类,用共识算法存少量变化慢的协调数据。它提供锁、租约、防护令牌、故障检测和变更通知。
第一次出现:第 10 章 §3.3
第 11 章起
MapReduceMapReduce
一种批处理编程模型:用户只写 mapper(从每条记录里取出键和值)和 reducer(处理同一个键的全部值)两个函数,中间按键排序和分组由框架完成。2004 年由 Google 发表,现在基本被数据流引擎取代。
第一次出现:第 11 章 §0
dataflow engine数据流引擎
把一整条多阶段的工作流当作一个作业来执行的批处理引擎,比如 Spark、Flink。只在需要的地方排序,中间结果放在内存或本地盘,下游不必等上游全部跑完。
第一次出现:第 11 章 §3.2
shuffle洗牌
批处理里的分布式排序:按键的哈希把上游的输出分给下游各个任务,在各任务内排好序,保证同一个键落到同一个任务、而且挨在一起。连接和分组都靠它;结果是有序的,不是随机的。
第一次出现:第 11 章 §3.3
第 12 章起
change data capture (CDC)变更数据捕获
把写进数据库的每一个变更从复制日志里取出来,按提交顺序作为一条流交给搜索索引、缓存、数据仓库这类派生系统。这样数据库就成了主,其他系统都是它的从。
第一次出现:第 12 章 §2.2