Files
interview/questions/01-分布式系统/CAP理论和BASE理论.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:10:53 +08:00

440 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CAP 理论和 BASE 理论
## 问题
1. 什么是 CAP 理论CAP 三者为什么不可兼得?
2. 什么是 BASE 理论?
3. CP、AP、AP 架构分别适用于什么场景?
4. Zookeeper、Eureka、Nacos、Consul 分别是 CP 还是 AP
5. 在实际项目中如何权衡一致性、可用性、分区容错性?
---
## 标准答案
### 1. CAP 理论
#### **定义**
CAP 是指分布式系统中的三个核心指标:
| 指标 | 说明 | 示例 |
|------|------|------|
| **Consistency一致性** | 所有节点在同一时间看到相同的数据 | 写入后,所有节点立即读取到新数据 |
| **Availability可用性** | 系统持续提供服务,每个请求都能得到响应 | 即使部分节点故障,系统仍能响应 |
| **Partition Tolerance分区容错性** | 系统在网络分区时仍能继续运行 | 节点间网络断开,系统仍能工作 |
---
#### **CAP 定理**
**一个分布式系统最多只能同时满足两项**
```
┌─────────────────────────────────────┐
│ CAP 三选二 │
│ │
│ CA ────┐ │
│ │ │
│ ╲ │
│ ╲ │
│ ╲ │
│ ●────────●──────● │
│ C P A │
│ │
│ CP AP CA │
└─────────────────────────────────────┘
```
**为什么?**(证明)
```
场景:两个节点 N1、N2网络分区P
情况 1保证 C一致性
├─ N1 写入数据
└─ 为了保证一致性N2 必须拒绝读取(牺牲 A
情况 2保证 A可用性
├─ N1 写入数据
└─ 为了保证可用性N2 返回旧数据(牺牲 C
结论在有分区P的情况下C 和 A 无法同时满足
```
---
#### **CP、AP、CA 架构**
**1. CP一致性 + 分区容错)**
**特点**
- 保证数据一致性
- 分区时部分节点不可用
**适用场景**
- 金融系统(转账、支付)
- 库存系统(超卖不可接受)
**代表系统**
- ZookeeperCP
- HBaseCP
- Redis ClusterCP主从切换时短暂不可用
**示例**
```java
// Zookeeper 写入流程
client.setData("/node", data);
// 等待大多数节点确认
// 如果网络分区,部分节点无法写入
```
---
**2. AP可用性 + 分区容错)**
**特点**
- 保证系统可用
- 分区时可能读到脏数据
**适用场景**
- 社交媒体(点赞、评论)
- 内容分发CDN
- 用户行为统计
**代表系统**
- CassandraAP
- DynamoDBAP
- EurekaAP
- DNSAP
**示例**
```java
// Cassandra 写入
session.execute("INSERT INTO users (id, name) VALUES (1, 'Alice')");
// 写入成功立即返回
// 数据可能尚未复制到其他节点(最终一致性)
```
---
**3. CA一致性 + 可用性)**
**注意****在分布式系统中CA 不存在**(因为网络分区不可避免)。
**CA 存在于**
- 单机系统RDBMS
- 传统关系型数据库MySQL、PostgreSQL
---
### 2. BASE 理论
#### **定义**
BASE 是对 CAP 中 AP 方案的补充,通过**牺牲强一致性**来获得**高可用性**。
| 指标 | 说明 | 示例 |
|------|------|------|
| **Basically Available基本可用** | 系统出现故障时,允许损失部分可用性 | 秒杀时拒绝部分请求 |
| **Soft state软状态** | 允许数据存在中间状态 | 订单状态:待支付 → 已支付 |
| **Eventually consistent最终一致性** | 数据最终会达到一致状态 | 支付后 1 秒内到账 |
---
#### **BASE vs ACID**
| 特性 | ACID传统数据库 | BASENoSQL |
|------|-------------------|---------------|
| **一致性** | 强一致性(立即) | 最终一致性(延迟) |
| **可用性** | 可能(锁、事务) | 高(无锁、异步) |
| **隔离性** | 严格(锁) | 松散 |
| **持久性** | 强 | 弱(可能丢失) |
---
#### **最终一致性的实现**
**1. 读时修复Read Repair**
```java
// 读取时检查一致性
public User getUser(Long userId) {
// 从多个节点读取
User user1 = node1.get(userId);
User user2 = node2.get(userId);
// 发现不一致,修复
if (!user1.equals(user2)) {
// 使用版本号或时间戳决定哪个更新
User latest = user1.getVersion() > user2.getVersion() ? user1 : user2;
// 异步修复旧数据
asyncRepair(latest);
return latest;
}
return user1;
}
```
---
**2. 写时修复Write Repair**
```java
// 写入时同步到所有节点
public void saveUser(User user) {
// 写入主节点
masterNode.save(user);
// 异步同步到从节点
for (Node slave : slaves) {
CompletableFuture.runAsync(() -> {
slave.save(user);
});
}
}
```
---
**3. 异步复制**
```
主节点收到写入
立即返回成功
异步复制到从节点
最终一致
```
---
### 3. 主流注册中心对比
#### **ZookeeperCP**
**特点**
- 保证一致性ZAB 协议)
- Leader 挂了会重新选举(期间不可用)
**适用场景**
- 需要强一致性
- 对可用性要求不高(如配置中心)
**示例**
```java
// Zookeeper 注册
zk.create("/services/order/192.168.1.10:8080", data, ZooDefs.Ids.OPEN, NodeMode.EPHEMERAL);
```
---
#### **EurekaAP**
**特点**
- 保证可用性
- 客户端缓存注册信息
- 网络分区时仍能提供服务
**适用场景**
- 对可用性要求高
- 可容忍短暂的服务发现不准确
**示例**
```java
// Eureka 注册
@Bean
public EurekaInstanceBeanBean eurekaInstanceBean(InetAddress inetAddress) {
EurekaInstanceBeanBean bean = new EurekaInstanceBeanBean();
bean.setHostname(inetAddress.getHostAddress());
bean.setAppName("order-service");
bean.setNonSecurePort(8080);
return bean;
}
```
---
#### **NacosAP + CP**
**特点**
- 支持 AP 和 CP 切换
- 默认 AP临时实例
- 可配置 CP持久化实例
**配置**
```yaml
# Nacos 配置
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
ephemeral: true # true=AP, false=CP
```
---
#### **ConsulCP**
**特点**
- 保证一致性Raft 协议)
- 支持 KV 存储
- 支持健康检查
**适用场景**
- 服务发现
- 配置中心
- 分布式锁
---
### 4. 实际项目应用
#### **场景 1订单系统CP**
**需求**
- 不能超卖
- 库存数据必须准确
**方案**
```
1. 使用分布式锁Redis、Zookeeper
2. 数据库使用强一致性事务
3. 库存扣减使用串行化
```
**代码**
```java
@Transactional
public void createOrder(Order order) {
// 1. 获取分布式锁
RLock lock = redissonClient.getLock("product:" + order.getProductId());
lock.lock();
try {
// 2. 查询库存
Product product = productMapper.selectById(order.getProductId());
if (product.getStock() < order.getQuantity()) {
throw new BusinessException("库存不足");
}
// 3. 扣减库存
product.setStock(product.getStock() - order.getQuantity());
productMapper.updateById(product);
// 4. 创建订单
orderMapper.insert(order);
} finally {
lock.unlock();
}
}
```
---
#### **场景 2社交点赞AP**
**需求**
- 高并发点赞
- 允许点赞数短暂不准确
**方案**
```
1. 先更新缓存Redis
2. 异步同步到数据库
3. 最终一致1 秒内)
```
**代码**
```java
public void like(Long userId, Long postId) {
// 1. 更新缓存(立即返回)
redisTemplate.opsForSet().add("post:" + postId + ":likes", userId);
// 2. 异步更新数据库
CompletableFuture.runAsync(() -> {
likeMapper.insert(new Like(userId, postId));
});
}
public Long getLikeCount(Long postId) {
// 1. 先查缓存
Long count = redisTemplate.opsForSet().size("post:" + postId + ":likes");
// 2. 如果缓存不存在,查数据库
if (count == null || count == 0) {
count = likeMapper.countByPostId(postId);
redisTemplate.opsForValue().set("post:" + postId + ":count", count, 1, TimeUnit.HOURS);
}
return count;
}
```
---
#### **场景 3库存同步最终一致性**
**需求**
- 多个仓库库存同步
- 允许短暂不一致
**方案**
```
1. 使用消息队列RocketMQ
2. 事务消息保证不丢失
3. 消费者重试保证最终一致
```
**代码**
```java
// 1. 发送事务消息
@Transactional
public void updateStock(Long productId, int quantity) {
// 更新数据库
productMapper.updateStock(productId, quantity);
// 发送事务消息
Message msg = new Message("StockTopic", "StockUpdate",
JSON.toJSONString(new StockUpdateEvent(productId, quantity)).getBytes());
rocketMQTemplate.sendMessageInTransaction(msg, null);
}
// 2. 消费消息
@RocketMQMessageListener(topic = "StockTopic", consumerGroup = "stock-consumer")
public class StockConsumer implements RocketMQListener<StockUpdateEvent> {
@Override
public void onMessage(StockUpdateEvent event) {
// 同步到其他仓库
warehouseService.syncStock(event.getProductId(), event.getQuantity());
}
}
```
---
### 5. 阿里 P7 加分项
**深度理解**
- 理解 CAP 理论的局限性(如网络延迟、时钟问题)
- 理解各种一致性协议Paxos、Raft、ZAB
- 理解分布式事务的权衡
**实战经验**
- 有设计 CP 或 AP 系统的经验
- 有处理数据不一致问题的经验
- 有最终一致性调优的经验
**架构能力**
- 能根据业务特点选择合适的架构
- 能设计混合架构(部分 CP、部分 AP
- 能设计数据修复和补偿机制
**技术选型**
- 了解各种注册中心和存储系统的 CAP 特性
- 能根据业务特点选择合适的技术
- 有分布式系统设计经验