DDIA Part 2: 分布式数据

本文是 DDIA 第二部分的完整读书笔记,涵盖第 5-9 章:数据复制、数据分区、事务、分布式挑战、一致性与共识。


第5章:数据复制

5.1 复制的目的

目的 说明
高可用性 部分节点故障时系统仍可用
降低延迟 将数据放在离用户更近的地方
提高读吞吐 多个副本可以并行处理读请求

5.2 主从复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──────────────────────────────────────────────┐
│ 主从复制架构 │
├──────────────────────────────────────────────┤
│ 客户端写入 │
│ │ │
│ ▼ │
│ ┌────────┐ 复制日志 ┌────────┐ │
│ │ 主节点 │ ─────────> │ 从节点1 │ │
│ │(Leader)│ │(Follower)│ │
│ └────────┘ └────────┘ │
│ │ │ │
│ │ 复制日志 │ │
│ ▼ ▼ │
│ ┌────────┐ ┌────────┐ │
│ │ 从节点2 │ │ 从节点3 │ │
│ └────────┘ └────────┘ │
│ │
│ 客户端可以从任意节点读取 │
└──────────────────────────────────────────────┘

同步复制 vs 异步复制

方式 优点 缺点
同步 数据一致,从节点数据最新 延迟高,从节点故障会阻塞
异步 延迟低,不受从节点影响 数据可能丢失
半同步 平衡一致性和可用性 实现复杂

故障转移(Failover)

1
2
3
4
5
1. 检测主节点故障(心跳超时)
2. 选举新主节点(选择数据最新的节点)
3. 重新配置系统
- 客户端发送写请求到新主节点
- 其他从节点从新主节点复制

问题:数据丢失、脑裂、超时设置

5.3 复制延迟问题

读己之写一致性:用户写入后立即读取可能看到旧数据

单调读:用户刷新页面可能路由到不同从节点,看到数据”回退”

一致前缀读:因果关系打乱(先看到回答再看到问题)

5.4 多主复制

1
2
3
4
┌──────────┐         ┌──────────┐
│ 数据中心1 │ <─────> │ 数据中心2 │
│ (主节点1) │ 异步 │ (主节点2) │
└──────────┘ └──────────┘

冲突解决策略

  • 最后写入胜出(LWW)
  • 合并值
  • CRDT
  • 自定义逻辑

5.5 无主复制(Quorum)

公式W + R > N

符号 含义
N 副本总数
W 写入需要确认的副本数
R 读取需要查询的副本数
1
2
3
4
示例:N=3, W=2, R=2
写入成功需要 2 个副本确认
读取需要查询 2 个副本
W + R = 4 > N = 3 → 保证读到最新值

第6章:数据分区

6.1 分区的目的

将大数据集分散到多个节点,每个节点只存储部分数据

6.2 分区策略

按键范围分区

1
分区1: A-F    分区2: G-N    分区3: O-Z

优点:支持范围查询
缺点:可能导致热点

按哈希分区

1
分区 = hash(key) % N

优点:均匀分布
缺点:不支持范围查询

6.3 次级索引分区

类型 特点
本地索引 写入快,查询需要scatter-gather
全局索引 查询快,写入需要分布式事务

6.4 分区再平衡

策略 说明
固定分区数 预先创建多个分区
动态分区 根据数据大小自动分裂/合并
按节点分区 每个节点固定数量的分区

第7章:事务

7.1 ACID 特性

特性 说明
原子性 (Atomicity) 全部成功或全部失败
一致性 (Consistency) 从一个有效状态到另一个有效状态
隔离性 (Isolation) 并发事务互不干扰
持久性 (Durability) 提交后数据不丢失

7.2 隔离级别

级别 脏读 不可重复读 幻读
读未提交
读已提交
可重复读
可串行化

7.3 串行化实现

真正的串行执行

  • 单线程处理事务
  • 适合事务短、数据在内存

两阶段锁定(2PL)

1
2
增长阶段:只能获取锁
收缩阶段:只能释放锁

可串行化快照隔离(SSI)

  • 乐观并发控制
  • 检测冲突后回滚

7.4 分布式事务

两阶段提交(2PC)

1
2
3
4
5
6
7
阶段1(准备):
协调者 ──准备?──> 所有参与者
<──准备好──

阶段2(提交):
协调者 ──提交──> 所有参与者
<──完成──

问题:协调者故障时参与者阻塞


第8章:分布式系统的挑战

8.1 不可靠的网络

  • 请求可能丢失
  • 请求可能排队很久
  • 响应可能丢失
  • 无法区分节点故障和网络故障

8.2 不可靠的时钟

时钟类型 用途
墙上时钟 获取当前时间(NTP同步)
单调时钟 测量时间间隔

问题:不同机器时钟可能不同步

8.3 进程暂停

  • GC 暂停
  • 虚拟机暂停
  • 页面交换

8.4 拜占庭故障

节点可能发送任意消息(故意或无意)


第9章:一致性与共识

9.1 一致性模型

1
2
3
弱 ←─────────────────────────────────────→ 强

最终一致性 因果一致性 顺序一致性 线性一致性

9.2 线性一致性

系统表现得好像只有一个数据副本,所有操作都是原子的

1
2
3
4
5
6
7
8
时间线:
────────────────────────────────────────>

客户端A: ├── 写入 x=1 ──┤
客户端B: ├── 读取 x ──┤ → 必须返回 1
客户端C: ├── 读取 x ──┤ → 必须返回 1

一旦任何客户端读到新值,所有后续读取都必须返回新值

9.3 CAP 定理

1
2
3
4
5
6
7
8
9
10
11
      C (Consistency)
╱╲
╱ ╲
╱ 只能 ╲
╱ 选择2个 ╲
A ────────── P
(Availability) (Partition Tolerance)

网络分区时必须选择:
- CP:保证一致性,牺牲可用性
- AP:保证可用性,牺牲一致性

9.4 共识算法

共识的性质

性质 说明
一致同意 所有节点决定相同的值
完整性 决定的值必须是某个节点提议的
终止性 最终会做出决定

9.5 Raft 算法

1
2
3
4
5
6
7
8
9
10
11
┌──────────┐
│ 领导者 │ ← 处理所有客户端请求
│ (Leader) │
└──────────┘

│ 复制日志

┌──────────┐ ┌──────────┐
│ 跟随者1 │ │ 跟随者2 │
│(Follower)│ │(Follower)│
└──────────┘ └──────────┘

选举流程

  1. 跟随者超时未收到心跳
  2. 转变为候选人,增加任期
  3. 向其他节点请求投票
  4. 获得多数票则成为领导者

9.6 Paxos 算法

1
2
3
4
5
6
7
阶段1(Prepare):
提议者 ──Prepare(n)──> 接受者
<──Promise──

阶段2(Accept):
提议者 ──Accept(n,v)──> 接受者
<──Accepted──

Raft vs Paxos

方面 Raft Paxos
可理解性
领导者 稳定领导者 每次共识可能不同
日志 连续日志 可能有空洞

9.7 共识的应用

  • ZooKeeper:Kafka 使用进行领导者选举
  • etcd:Kubernetes 存储集群状态
  • Consul:服务发现和配置

本章关键要点

  1. 复制的核心挑战是处理变更
  2. 异步复制有数据丢失风险
  3. Quorum 使用 W + R > N 保证一致性
  4. 分区支持水平扩展
  5. 隔离级别是性能与一致性的权衡
  6. 线性一致性是最强的一致性保证
  7. CAP 定理表明网络分区时需要取舍
  8. Raft 比 Paxos 更易理解

延伸阅读

  • 《Amazon Dynamo》论文:无主复制经典论文
  • 《Paxos Made Simple》:Lamport 的简化版 Paxos
  • 《In Search of an Understandable Consensus Algorithm》:Raft 论文