Skip to content

Java分布式架构面试题库 ​

生成时间:2026-05-24 21:57


【面试题】1. CAP定理中为什么只能三选二?在实际系统中如何权衡? ​

【标准答案】 CAP定理的核心是:一个分布式系统不可能同时满足一致性(C)、可用性(A)、分区容错性(P)。

为什么只能三选二?因为网络分区是客观存在的,P无法避免。当分区发生时,系统必须在C和A之间做选择——要么等待分区恢复保证一致性但牺牲可用性,要么继续响应请求保证可用性但可能返回旧数据。

实际权衡策略:

  • CP系统(如Zookeeper、HBase):强一致性优先,网络分区时部分节点不可用。适合金融转账、库存扣减等对一致性要求极高的场景。
  • AP系统(如Cassandra、Eureka):可用性优先,分区时继续服务但可能读到旧数据。适合社交动态、商品展示等容忍短暂不一致的场景。
  • 注意:实际上很多系统在不同层面做取舍,比如Redis Cluster是AP但支持异步复制的一致性读,MySQL主从是AP但可以通过半同步提升一致性。

面试加分点:提到"实际上没有真正的CA系统,因为P是分布式系统固有的"。


【面试题】2. Redis分布式锁如何解决锁超时导致的安全问题? ​

【标准答案】 Redis分布式锁的核心问题是:如果持有锁的客户端执行时间超过锁的过期时间,锁会自动释放,其他客户端获得锁后可能导致并发问题。

解决方案:

  1. 锁续期(看门狗机制):

    • Redisson实现的Watchdog,后台线程定期续期(默认每10秒续期到30秒)
    • 业务没执行完锁不会过期,执行完自动停止续期
  2. 合理设置超时时间:

    • 根据业务最长执行时间设置,留出buffer
    • 比如业务最大执行5秒,锁设置10秒
  3. Redlock算法(多节点高可用):

    • 在多个Redis实例上加锁,大多数成功才算成功
    • 防止单节点故障导致锁失效
  4. 锁释放校验:

    • 释放锁时检查value是否是自己设置的(Lua脚本原子操作)
    • 防止误删其他客户端的锁

实际落地:生产环境直接用Redisson,自带看门狗、可重入锁、读写锁,不用自己造轮子。


【面试题】3. TCC分布式事务模式下,Confirm阶段失败了怎么办? ​

【标准答案】 TCC(Try-Confirm-Cancel)是柔性事务方案,Confirm失败是常见问题。

失败处理机制:

  1. 重试机制:

    • Confirm失败后,事务协调器不断重试(指数退避策略)
    • 直到成功或达到最大重试次数
    • 因为Confirm是确认操作,必须成功才能保证事务完整性
  2. 幂等性设计:

    • Confirm操作必须幂等,多次执行结果相同
    • 通过业务流水号去重,执行前先查状态
  3. 人工介入:

    • 重试N次仍失败,转入人工处理队列
    • 记录完整的事务日志,便于排查和补偿
  4. 定时任务扫描:

    • 后台任务扫描长时间未完成的事务
    • 触发重试或报警

关键点:Confirm没有Cancel,只能重试到底。这也是TCC的"刚性"体现——Try之后必须有个明确结果。

实际经验:Seata TCC模式下,Confirm失败会记录在事务日志表,后台有补偿线程自动重试。业务代码要确保Confirm幂等。


【面试题】4. Snowflake雪花算法时钟回拨问题怎么解决? ​

【标准答案】 Snowflake依赖服务器时间,时钟回拨会导致ID重复或时间倒退。

解决方案:

  1. 回拨检测+等待:

    • 记录上次生成ID的时间戳
    • 发现时间回拨,等待到时间追上
    • 小回拨(比如几毫秒)可以等,大回拨需要其他策略
  2. 回拨拒绝:

    • 回拨超过阈值(比如5ms),直接报错或返回备用方案
    • 适合对连续性要求不高的场景
  3. 预留ID段:

    • 百度UidGenerator方案:提前生成一批ID缓存
    • 时钟回拨时使用缓存的ID
    • 平时异步补充缓存
  4. 时钟回拨位:

    • 美团Leaf方案:用部分位存储回拨次数
    • 同一毫秒内回拨也能区分
  5. NTP时钟同步优化:

    • 禁用NTP主动调整,只做监控
    • 发现时钟偏差报警,人工介入

生产建议:

  • 物理机避免虚拟机时钟漂移
  • 监控系统时间变化
  • 使用UidGenerator或Leaf等成熟方案

【面试题】5. 缓存穿透、击穿、雪崩的区别和解决方案? ​

【标准答案】 这三个问题都是缓存失效导致的数据库压力问题,但场景不同。

缓存穿透:查询不存在的数据,缓存没命中,直接打到数据库。

  • 解决方案:
    • 布隆过滤器过滤不存在的key
    • 空值也缓存,设置短过期时间(如5分钟)
    • 参数校验拦截非法请求

缓存击穿:某个热点key过期瞬间,大量请求同时访问数据库。

  • 解决方案:
    • 热点key永不过期,异步更新
    • 互斥锁:缓存失效时只允许一个线程查库重建缓存
    • 提前续期:访问时延长过期时间

缓存雪崩:大量key同时过期,或Redis宕机,数据库压力骤增。

  • 解决方案:
    • 过期时间加随机值,避免同时失效
    • 多级缓存:本地缓存+Redis
    • Redis高可用:主从+哨兵+Cluster
    • 限流降级:保护数据库

实际落地:

  • 穿透:布隆过滤器+空值缓存
  • 击穿:热点key预热+互斥锁
  • 雪崩:随机过期+多级缓存+熔断

面试加分:提到"双十一热点商品预热到缓存,设置随机过期时间防止雪崩"。


【面试题】6. JWT无状态方案如何实现Token刷新和注销? ​

【标准答案】 JWT无状态的好处是不需要服务端存储,但也带来了刷新和注销难题。

Token刷新方案:

  1. 双Token机制:

    • Access Token:有效期短(如2小时),用于访问
    • Refresh Token:有效期长(如7天),用于刷新Access Token
    • Refresh Token存储在Redis中,可主动失效
  2. 滑动刷新:

    • 用户活跃时自动延长Token有效期
    • 后台静默刷新,用户无感知
  3. Token黑名单:

    • 注销时将Token加入Redis黑名单
    • 每次请求检查黑名单(牺牲部分性能)

注销方案:

  1. Token黑名单:

    • 注销时将未过期的Token加入黑名单
    • 设置过期时间等于Token剩余有效期
    • 访问时检查黑名单
  2. 版本号机制:

    • Token中包含版本号字段
    • 用户数据中维护当前版本号
    • 注销时更新版本号,旧Token失效
  3. Refresh Token撤销:

    • 注销时删除Redis中的Refresh Token
    • Access Token短时间后自然过期

实际选择:

  • 安全要求高:黑名单+双Token
  • 性能要求高:版本号机制+短过期时间

【面试题】7. 令牌桶和漏桶算法的区别?生产环境如何选择? ​

【标准答案】 两者都是限流算法,但特性和适用场景不同。

漏桶算法:

  • 原理:请求先进队列,以固定速率流出处理
  • 特点:流出速率恒定,能平滑突发流量
  • 缺点:无法应对突发请求,队列满则丢弃
  • 场景:保护数据库等处理能力固定的系统

令牌桶算法:

  • 原理:以固定速率往桶里放令牌,请求拿令牌才能处理
  • 特点:桶有容量,可以应对突发流量(桶内有令牌时)
  • 优势:既有限流又有一定弹性
  • 场景:API网关、业务限流

核心区别:

  • 漏桶:强制恒定速率,突发流量直接丢弃
  • 令牌桶:允许一定程度的突发,桶内令牌可瞬时使用

生产选择:

  • API限流:令牌桶(如Guava RateLimiter、Redis+Lua实现)
  • 数据库保护:漏桶(平滑请求,防止突发打挂)
  • 分布式限流:Redis+Lua实现令牌桶,集群统一计数

实际落地:

java
// Guava RateLimiter(单机)
RateLimiter limiter = RateLimiter.create(100); // 100 QPS
if (limiter.tryAcquire()) {
    // 处理请求
}

面试加分:提到"Sentinel同时支持QPS限流(令牌桶)和并发线程数限流"。


【面试题】8. Raft算法中Leader选举的具体流程? ​

【标准答案】 Raft是强一致性算法,Leader选举是其核心机制。

选举流程:

  1. 初始状态:

    • 所有节点都是Follower状态
    • 每个节点有随机选举超时时间(150-300ms)
  2. 超时触发:

    • Follower在选举超时时间内未收到Leader心跳
    • 转为Candidate状态,任期号+1
  3. 发起投票:

    • Candidate先给自己投票
    • 向其他节点发送RequestVote RPC
  4. 投票判断:

    • 收到投票请求的节点检查:
      • 候选人任期 >= 自己的任期
      • 候选人日志至少和自己一样新
    • 满足条件则投票,每个任期只能投一次
  5. 选举结果:

    • 获得多数派投票(N/2+1)→ 成为Leader
    • 收到更高任期的心跳 → 退回Follower
    • 选举超时未获多数 → 重新选举
  6. Leader上任:

    • 立即发送心跳确认地位
    • 后续所有请求通过Leader处理

关键点:

  • 随机超时避免同时选举(脑裂)
  • 多数派机制保证只有一个Leader
  • 日志新旧判断防止数据丢失

实际应用:Etcd、Consul都用Raft,3节点集群容忍1节点故障。


【面试题】9. Zookeeper临时节点和持久节点的应用场景? ​

【标准答案】 Zookeeper节点类型决定了生命周期和用途。

持久节点(Persistent):

  • 特点:创建后永久存在,直到主动删除
  • 应用场景:
    • 配置中心:存储配置信息
    • 命名服务:服务注册信息
    • 路由信息:存储路由规则

临时节点(Ephemeral):

  • 特点:客户端会话结束自动删除
  • 应用场景:
    • 服务注册:服务下线自动注销
    • 分布式锁:锁持有者宕机自动释放
    • Leader选举:候选者创建临时节点,创建成功者为Leader

临时顺序节点:

  • 特点:临时节点+自动递增序号
  • 应用场景:
    • 公平锁:序号最小的获得锁
    • 分布式队列:按序号顺序处理

持久顺序节点:

  • 特点:持久节点+自动递增序号
  • 应用场景:
    • 全局有序ID生成

实际案例:

java
// 服务注册(临时节点)
zk.create("/services/order-service/host:port", data, 
          ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

// 分布式锁(临时顺序节点)
zk.create("/lock/order-", data,
          ZooDefs.Ids.OPEN_ACL_UNsafe, CreateMode.EPHEMERAL_SEQUENTIAL);

面试加分:提到"Curator框架封装了这些细节,Recipe包提供现成的分布式锁实现"。


【面试题】10. 分布式链路追踪中TraceId如何在整个调用链中传递? ​

【标准答案】 TraceId是链路追踪的核心,需要在整个调用链中透传。

传递机制:

  1. RPC调用传递:

    • Dubbo:RpcContext中设置attachment
    • Feign:RequestInterceptor添加Header
    • gRPC:Metadata中传递
  2. HTTP调用传递:

    • 放在HTTP Header中:X-Trace-Id: xxx
    • 下游服务从Header提取并继续传递
  3. 异步调用传递:

    • 线程池:使用装饰过的Runnable/Callable,在任务创建时捕获上下文
    • 消息队列:消息Header中携带TraceId
    • Spring的@Async:TaskDecorator自动传递
  4. 跨服务框架:

    • Spring Cloud Sleuth:自动注入TraceId到Header
    • Micrometer Tracing:统一抽象,适配多种Tracing后端
    • SkyWalking Agent:字节码增强,无侵入传递

技术实现:

java
// 主线程
String traceId = TraceContext.traceId();
MDC.put("traceId", traceId);

// 跨线程传递(使用TransmittableThreadLocal)
ExecutorService executor = TtlExecutors.getTtlExecutorService(rawExecutor);

// RPC传递
RpcContext.getContext().setAttachment("traceId", traceId);

实际方案:

  • 微服务:Spring Cloud Sleuth + Zipkin
  • 性能要求高:SkyWalking Agent(无侵入,性能损耗<5%)
  • 自研框架:TransmittableThreadLocal + Header传递

面试加分:提到"异步场景用阿里TTL库,解决InheritableThreadLocal线程池复用问题"。


本次生成题目覆盖:

  • 理论基础:CAP定理
  • 分布式锁:Redis锁续期
  • 分布式事务:TCC Confirm失败处理
  • 分布式ID:Snowflake时钟回拨
  • 缓存:穿透/击穿/雪崩
  • 分布式会话:JWT刷新注销
  • 限流:令牌桶vs漏桶
  • 一致性算法:Raft选举
  • 协调服务:Zookeeper节点类型
  • 链路追踪:TraceId传递

共计10题,覆盖10个核心考点