Generated comprehensive interview preparation materials covering: - Distributed systems (transactions, locks, ID generation, consistency) - Database (indexing, sharding, replication, transactions) - Caching (Redis, cache problems, distributed lock) - Message queues (RocketMQ, Kafka) - Concurrency (ThreadLocal, ConcurrentHashMap, thread pools) - JVM (GC, memory, tuning) - System design (seckill, short URL, IM, feed, LBS) - Algorithms (B+ tree, LRU, Red-Black tree, Skip list, Timing wheel) - Network (TCP/IP, HTTP/HTTPS) - Security (encryption, SQL injection, XSS) - Performance tuning - Design patterns - Microservices (Spring Boot, Gateway, Service Mesh) - Container orchestration (Kubernetes, Docker) - CI/CD, observability Each file includes: - Detailed questions - Comprehensive answers - Code examples - Real project experience - Alibaba P7 level requirements 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>
10 KiB
10 KiB
CAP 理论和 BASE 理论
问题
- 什么是 CAP 理论?CAP 三者为什么不可兼得?
- 什么是 BASE 理论?
- CP、AP、AP 架构分别适用于什么场景?
- Zookeeper、Eureka、Nacos、Consul 分别是 CP 还是 AP?
- 在实际项目中如何权衡一致性、可用性、分区容错性?
标准答案
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(一致性 + 分区容错)
特点:
- 保证数据一致性
- 分区时部分节点不可用
适用场景:
- 金融系统(转账、支付)
- 库存系统(超卖不可接受)
代表系统:
- Zookeeper(CP)
- HBase(CP)
- Redis Cluster(CP,主从切换时短暂不可用)
示例:
// Zookeeper 写入流程
client.setData("/node", data);
// 等待大多数节点确认
// 如果网络分区,部分节点无法写入
2. AP(可用性 + 分区容错)
特点:
- 保证系统可用
- 分区时可能读到脏数据
适用场景:
- 社交媒体(点赞、评论)
- 内容分发(CDN)
- 用户行为统计
代表系统:
- Cassandra(AP)
- DynamoDB(AP)
- Eureka(AP)
- DNS(AP)
示例:
// 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(传统数据库) | BASE(NoSQL) |
|---|---|---|
| 一致性 | 强一致性(立即) | 最终一致性(延迟) |
| 可用性 | 可能(锁、事务) | 高(无锁、异步) |
| 隔离性 | 严格(锁) | 松散 |
| 持久性 | 强 | 弱(可能丢失) |
最终一致性的实现
1. 读时修复(Read Repair):
// 读取时检查一致性
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):
// 写入时同步到所有节点
public void saveUser(User user) {
// 写入主节点
masterNode.save(user);
// 异步同步到从节点
for (Node slave : slaves) {
CompletableFuture.runAsync(() -> {
slave.save(user);
});
}
}
3. 异步复制:
主节点收到写入
↓
立即返回成功
↓
异步复制到从节点
↓
最终一致
3. 主流注册中心对比
Zookeeper(CP)
特点:
- 保证一致性(ZAB 协议)
- Leader 挂了会重新选举(期间不可用)
适用场景:
- 需要强一致性
- 对可用性要求不高(如配置中心)
示例:
// Zookeeper 注册
zk.create("/services/order/192.168.1.10:8080", data, ZooDefs.Ids.OPEN, NodeMode.EPHEMERAL);
Eureka(AP)
特点:
- 保证可用性
- 客户端缓存注册信息
- 网络分区时仍能提供服务
适用场景:
- 对可用性要求高
- 可容忍短暂的服务发现不准确
示例:
// Eureka 注册
@Bean
public EurekaInstanceBeanBean eurekaInstanceBean(InetAddress inetAddress) {
EurekaInstanceBeanBean bean = new EurekaInstanceBeanBean();
bean.setHostname(inetAddress.getHostAddress());
bean.setAppName("order-service");
bean.setNonSecurePort(8080);
return bean;
}
Nacos(AP + CP)
特点:
- 支持 AP 和 CP 切换
- 默认 AP(临时实例)
- 可配置 CP(持久化实例)
配置:
# Nacos 配置
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
ephemeral: true # true=AP, false=CP
Consul(CP)
特点:
- 保证一致性(Raft 协议)
- 支持 KV 存储
- 支持健康检查
适用场景:
- 服务发现
- 配置中心
- 分布式锁
4. 实际项目应用
场景 1:订单系统(CP)
需求:
- 不能超卖
- 库存数据必须准确
方案:
1. 使用分布式锁(Redis、Zookeeper)
2. 数据库使用强一致性事务
3. 库存扣减使用串行化
代码:
@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 秒内)
代码:
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. 消费者重试保证最终一致
代码:
// 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 特性
- 能根据业务特点选择合适的技术
- 有分布式系统设计经验