第3章 分布式系统核心概念

CAP理论、一致性模型、负载均衡与分布式ID是分布式系统的地基。面试中常用来考察你对“权衡”的理解——没有完美方案,只有适合业务的取舍。本章通过问答卡片+项目模板,帮你建立结构化的回答框架。

⚠️ 面试核心信号:不要死记组合,要能结合具体业务场景说明你做过的选择,并给出量化指标(如峰值QPS、一致性等级要求)。
CAP 权衡框架 C:强一致性 A:高可用性 P:分区容错 场景:订单 选择 CP(ZooKeeper) 场景:用户通知 选择 AP(Eureka) 场景:日志 最终一致(Kafka) 面试加分:先说明 P 是必定存在的约束,再根据业务选择 C 或 A

📌 面试问答 1

面试问题:请解释 CAP 理论,以及在实际分布式系统中你如何做权衡?

面试官考察点:

  • 是否理解 CAP 三个属性的真实含义(尤其是分区容忍性不可弃)
  • 能否结合具体技术选型(ZooKeeper vs Eureka)说明权衡逻辑
  • 是否清楚“三者不可兼得”的适用范围(只有网络分区时才需取舍)

回答框架:

  1. 定义 C(一致性)、A(可用性)、P(分区容忍性)
  2. 强调 P 是分布式系统必须满足的前提(网络分区不可避免)
  3. 引出 CP 与 AP 的选择:强一致牺牲部分可用性,高可用牺牲强一致
  4. 给出项目例子(如订单系统用 CP,用户通知用 AP)
  5. 补充最终一致性、补偿机制等降级策略

简短示例回答:

CAP 指一致性、可用性、分区容忍性。由于网络分区必然存在,实际上只能在 CP 与 AP 间选择。我在订单服务采用 CP(基于 Raft),确保支付与库存强一致;在用户积分通知场景采用 AP,通过异步消息最终一致,提升可用性。
⚠️ 可能追问:如果业务需要同时保证可用性和强一致,你怎么设计?(答:引入分布式事务协议如 2PC/Saga,配合幂等和补偿,但会牺牲性能) ⚠️ 避坑提醒:不要机械地说“三者只能选两个”,必须强调“正常运行时三者都可满足,只有分区时才需要取舍”。

📌 面试问答 2

面试问题:说说你知道的分布式一致性模型,以及你在项目中如何选择?

面试官考察点:

  • 是否了解线性一致性、因果一致性、最终一致性等常见模型
  • 能否根据业务对一致性的容忍度做选型
  • 是否了解实现技术(Raft/Quorum/CRDT)

回答框架:

  1. 梳理模型谱系:强一致 → 因果一致 → 最终一致 → 弱一致
  2. 每个模型的核心约束(如线性一致要求所有操作原子有序)
  3. 举例说明业务场景:交易用强一致,用户评论用最终一致
  4. 提及实现手段:Raft 实现强一致,Quorum NWR 实现最终一致,CRDT 实现无冲突合并

简短示例回答:

从强到弱:线性一致性(Raft)、因果一致性(CRDT)、最终一致性(DNS 复制)。我的项目在支付环节用 Raft 保证强一致,在用户动态流使用最终一致搭配版本向量,降低写入延迟。
⚠️ 可能追问:CRDT 的类型有哪些?如何解决冲突?(答:基于状态或基于操作,如 G-Counter、OR-Set,利用 LWW 或因果关系合并) ⚠️ 避坑提醒:不要把“最终一致性”当作万能解,须说明“最终”的时间窗口业务可接受,并配套幂等和补偿。

📌 面试问答 3

面试问题:分布式系统中如何生成全局唯一 ID?请列举方案并比较优劣。

面试官考察点:

  • 是否了解 UUID、雪花算法、号段模式、Redis incr 等常见方案
  • 能否从性能、有序性、时钟依赖、跨机房等维度分析
  • 是否清楚时钟回拨的问题及解决方案

回答框架:

  1. 分四类:UUID(简单但无序、长度大)、雪花(趋势递增、依赖时钟)、号段(DB 批量分配、支持自定义)、Redis(高性能但需持久化)
  2. 关键指标对比:性能、全局有序、时钟需求、跨机房支持
  3. 重点说雪花算法:64 位 = 时间戳 + 机器 ID + 序列号;时钟回拨时的暂停等待、备用时钟、预留位回拨策略

简短示例回答:

常用方案:UUID 性能好但无法排序;雪花算法趋势递增,需处理时钟回拨(我采用记录上次生成时间,回拨时暂停 10ms);号段模式适合分库分表场景,但依赖 DB 可用性。我在订单系统使用雪花 ID,保证在高并发下唯一且存储高效。
⚠️ 可能追问:如果机器时钟发生了大幅回拨(>5s),怎么处理?(答:报错并降级,或者切换到备用序列空间,同时告警人工校准) ⚠️ 避坑提醒:不要只说一种方案,更别忽略时钟回拨;面试官会期望看到你考虑过边界情况。

📊 核心概念对比:负载均衡策略

策略 核心原理 优点 缺点 适用场景
轮询(Round Robin) 按顺序依次分配请求 实现简单,无状态 不考虑后端负载,慢机器可能堆积 同配置无状态服务池
加权轮询(Weighted RR) 按权重比例分配 适应异构服务器 权重配置需手动调整 不同配置服务器混部
最小连接(Least Connections) 分配给当前连接数最少的节点 动态感知负载 需要维护连接状态,不支持长尾 长连接服务(如 WebSocket)
一致性哈希(Consistent Hashing) 对请求 key 哈希,映射到哈希环上的节点 节点增减时最小程度影响缓存命中 数据倾斜时可加虚拟节点 分布式缓存、Session 保持
随机(Random) 从可用节点随机选择一个 极简,无状态 分布不均 负载均衡非核心场景

🚀 项目实战案例:高并发订单服务

项目名称:大促秒杀订单系统(分布式架构)

业务背景:支持双 11 等大促活动,秒杀期间产生千万级 QPS,需要保证订单不超卖、支付幂等、库存扣减精确。

规模指标:

  • 日订单量:1 亿+
  • 峰值 TPS:10 万+
  • 服务节点数:300+ 台
  • 数据仓库:MySQL 分库分表 128 张,Redis 集群 64 节点

技术栈:

Go(gin + grpc)、Kafka(消息削峰)、Redis(redis-lock & incr)、
MySQL(分库分表 + 读写分离)、etcd(Raft 强一致存储配置)、
雪花 ID(时钟回拨容忍版)、Nginx + 一致性哈希负载均衡

核心难点:

  1. 分布式事务一致性:订单创建、库存扣减、支付三个操作需要保证最终一致,采用 Saga 模式 + 本地消息表,失败时通过补偿 job 回滚。
  2. 全局 ID 唯一且高性能:使用改进的雪花算法,增加时钟回拨检测(回拨 ≤ 50ms 时序列号递增跳过,否则告警暂停)。
  3. 负载均衡与流量削峰:前端 nginx 一致性哈希路由同一用户的请求到同一后端,减少事务冲突;Kafka 异步写入降低 DB 压力。

面试高频追问:

  • 如何保证订单幂等?(答:使用唯一流水号 + Redis setnx 去重表,先落地再执行)
  • 时钟回拨如果超过 1 秒你怎么处理?(答:直接终止服务,等待时钟修正并记录日志,切换到备用 ID 生成器)
  • 一致性哈希为什么选择 160 个虚拟节点?(答:使分布更均匀,经验值 150~200)
  • 本地消息表是否会丢失消息?(答:定时扫描未完成消息,配合对账和告警)

可迁移回答话术:

在秒杀场景下,我选择“最终一致性 + 补偿”策略而非强一致分布式事务,因为后者会大幅降低吞吐。
具体做法:用唯一流水号保证幂等,用本地消息表记录状态,通过定时补偿 job 确保最终一致。
负载均衡采用一致性哈希,将同一用户的请求始终路由到同一实例,减少分布式锁竞争。
📝 复习提示:本章四个概念是分布式面试的“必考计算题”。建议你准备一个自己实际用过的业务场景,把 CAP 取舍、一致性模型、ID 方案、负载均衡策略串起来讲。面试官很爱问“你们为什么选那个方案”,能说清楚“为什么”才算真正掌握。