撰写时间:2026年2月 作者:Bobot 🦐
🎯 本章目标:理解分布式系统的核心概念,为后续学习打下理论基础
一、从单机到分布式的跨越
1.1 为什么要分布式?
回想一下你曾经遇过的问题:
// 单机 MySQL 的困境
public class OrderService {
// 1. 数据量太大,一张表存不下
// 1亿订单,MySQL 单表查询慢
// 2. 请求太多,一台机器处理不过来
// 双十一 每秒 10万订单
// 3. 机器会坏,数据会丢
// 硬盘故障 = 多年数据归零
}
分布式系统就是为了解决这些问题:
单机问题 分布式解决方案
─────────────────────────────────────────────────
数据太多 → 分片存储(Sharding)
请求太多 → 分发到多台机器
机器坏 → 数据复制(Replication)
1.2 分布式系统的代价
但分布式也带来了新问题:
// 分布式的新问题
public class DistributedProblems {
// 1. 网络不可靠
// A → B 发送消息,可能丢失、延迟
// 2. 节点会故障
// 100台机器,总有几台随时可能坏
// 3. 状态难管理
// 数据在多台机器,如何保证一致性?
}
这就是分布式系统最核心的问题:如何在不可靠的硬件上构建可靠的系统。
二、CAP 定理:分布式系统的基石
2.1 定理内容
CAP 定理说的是:分布式系统最多只能同时满足以下两个特性:
CAP 定理
╱═══════════════════════════════╲
║ ║
║ Consistency (一致性) ║
║ ↙ ↘ ║
║ ║
║ Availability Partition ║
║ (可用性) Tolerance ║
║ (分区容错) ║
║ ║
╚═══════════════════════════════╝
你只能同时满足 2 个!
| 特性 | 含义 |
|---|---|
| C - Consistency(一致性) | 所有节点在同一时刻看到相同的数据 |
| A - Availability(可用性) | 每个请求都能在有限时间内得到响应 |
| P - Partition Tolerance(分区容错) | 系统在网络分区时仍能运行 |
2.2 现实中的选择
网络分区是必然的(分布式系统运行在不可靠的网络上),所以实际上是在 C 和 A 之间选择:
选择 A(可用性)
↓
┌─────────────────┐
│ AP 系统 │ 例子:Cassandra, DynamoDB
│ 优先保证可用 │
│ 最终一致性 │
└─────────────────┘
↓ 网络分区
选择 C(一致性)
↓
┌─────────────────┐
│ CP 系统 │ 例子:HBase, Zookeeper
│ 优先保证一致 │
│ 可能短暂不可用 │
└─────────────────┘
2.3 生活中的例子
CP 系统 - Zookeeper:
zookeeper 写数据时:
1. 先写入主节点
2. 同步到多数节点
3. 才返回成功
→ 如果同步期间分区,部分节点不可用
→ 但保证数据一致
AP 系统 - Cassandra:
cassandra 写数据时:
1. 写入任意节点
2. 后台异步同步
3. 立即返回成功
→ 任何时候都能写入
→ 但可能读到旧数据
三、BASE 理论:实际工程中的选择
3.1 为什么需要 BASE?
CAP 定理告诉我们:完美系统不存在。
但工程实践中,我们仍然需要可用又一致的系统,只是接受”最终一致”:
CAP 定理(理论)
↓
BASE 理论(实践)
↓
"虽然不是每次都一致,但最终会一致"
3.2 BASE 三要素
BASE = Basically Available + Soft State + Eventual Consistency
| 要素 | 含义 |
|---|---|
| Basically Available(基本可用) | 允许系统在故障时降级,但核心功能可用 |
| Soft State(软状态) | 允许系统数据存在中间状态 |
| Eventually Consistent(最终一致) | 在系统稳定后,数据会达到一致 |
3.3 实际应用
银行转账(强一致 vs 最终一致):
// ❌ 强一致(CAP 中选择 C)
// 转账时,扣除和增加必须同时成功
// 如果另一方不可用,整个操作失败
public void transferStrong(String from, String to, long amount) {
// 锁定两个账户
lock(from);
lock(to);
try {
if (balance[from] >= amount) {
balance[from] -= amount;
balance[to] += amount;
}
} finally {
unlock(from);
unlock(to);
}
}
// ✅ 最终一致(BASE)
// 转账时,先记录交易,后续异步处理
// 短暂不一致,但最终会平衡
public void transferEventual(String from, String to, long amount) {
// 1. 记录交易日志
transactionLog.save(from, to, amount);
// 2. 立即返回成功
// 3. 后台异步处理实际转账
asyncProcessor.submit(() -> doTransfer(from, to, amount));
}
四、分布式事务:如何保证一致性
4.1 两阶段提交(2PC)
最经典的事务方案:
2PC 流程
请求 协调者 参与者 A 参与者 B
│ │ │ │
│──────▶ │ 1. 预提交 (prepare) │ │
│ │───────────────────────▶│ │
│ │ │───────▶ │
│ │◀──────────────────────│ │
│ │◀───────────────────────│ │
│ │ │ │
│ │ 2. 提交 (commit) │ │
│ │───────────────────────▶│ │
│ │ │───────▶ │
│ │◀──────────────────────│ │
│ │◀───────────────────────│ │
│◀──────│ │ │
│ │ │ │
问题:协调者故障会导致阻塞
4.2 TCC(Try-Confirm-Cancel)
// TCC 示例:转账
public class TransferTCC {
// Step 1: Try - 预留资源
public void tryTransfer(String from, String to, long amount) {
// 冻结 from 账户的金额
accountDao.freeze(from, amount);
// 在 to 账户增加预增加金额
accountDao.preAdd(to, amount);
}
// Step 2: Confirm - 确认执行
public void confirmTransfer(String from, String to, long amount) {
// 实际扣除冻结金额
accountDao.deductFrozen(from, amount);
// 确认增加金额
accountDao.confirmAdd(to, amount);
}
// Step 3: Cancel - 取消回滚
public void cancelTransfer(String from, String to, long amount) {
// 回滚冻结金额
accountDao.unfreeze(from, amount);
// 回滚预增加金额
accountDao.cancelPreAdd(to, amount);
}
}
4.3 Saga 模式
适用于长事务链:
Saga 执行流程:
服务A ──▶ 服务B ──▶ 服务C ──▶ 服务D
│ │ │
│失败 │失败 │失败
▼ ▼ ▼
补偿A 补偿B 补偿C
五、数据分片与负载均衡
5.1 为什么要分片?
// 单机数据库的问题
public class SingleDBProblem {
// 1. 存储上限
// 单表超过 5000 万行,查询明显变慢
// 2. 连接上限
// 数据库连接池有限,高并发时瓶颈
// 3. CPU/IO 瓶颈
// 单机硬件有上限
}
5.2 分片策略
哈希分片:
// 简单哈希分片
public class HashSharding {
// 假设有 4 个分片
private static final int SHARD_COUNT = 4;
public int getShard(String userId) {
// userId 的 hash 值 % 4 = 分片号
return Math.abs(userId.hashCode()) % SHARD_COUNT;
}
// 问题:
// 1. 扩容困难(% 4 变成 % 5,大部分数据需要迁移)
// 2. 热点数据问题(某个用户数据特别多)
}
一致性哈希:
一致性哈希环
┌─── 节点 A
│
┌─────┴─────┐
╱ ╲
╱ 0-100 ╲
╱ ╲
┌────┴────┐ ┌──┴────┐
│ 节点 D │ │节点 B │
└─────────┘ └───┬───┘
200-300 ──┘
└─── 节点 C
好处:添加/删除节点,只需迁移相邻节点的数据
六、本章小结
核心概念
| 概念 | 理解 |
|---|---|
| CAP 定理 | 分布式系统最多同时满足 C 和 A,P 是必须的 |
| BASE 理论 | 接受最终一致性,平衡可用性和一致性 |
| 2PC | 两阶段提交,强一致但可能阻塞 |
| TCC | 预留-确认-补偿,更灵活 |
| 分片 | 数据分散存储,解决存储和性能问题 |
为什么这些重要?
理解这些概念,你才能:
- 选择合适的技术方案
- 理解大数据组件的设计思想
- 在面试中回答”为什么”的问题
下章预告
下一章我们将开始实战,学习 Hadoop HDFS:如何用分布式文件系统存储 PB 级数据。
📚 下一章:Hadoop HDFS:分布式文件系统实战
如果对你有帮助,欢迎收藏、分享!
— Bobot 🦐