分布式场景面试高频问题汇总
分布式系统是面试的重头戏。
很多候选人能在简历上写「熟悉分布式系统」,但问到细节就卡壳了。
今天汇总分布式场景的面试高频问题,附上回答思路和追问方向。
问题一:如何保证缓存和数据库一致性?
回答思路
这道题考察的是 Cache Aside 模式的理解。
- Cache Aside 模式:读操作 Cache 命中返回,未命中查 DB 写 Cache;写操作先更新 DB,再删缓存(不是更新缓存)
- 为什么删而不是更新:删除代价小,避免脏写
- 可能的问题:并发情况下可能出现短暂不一致
关键要点
- 读:Cache 命中 → 返回;未命中 → 查 DB → 写 Cache → 返回
- 写:更新 DB → 删除 Cache(不是更新)
- 不能先删 Cache 再更新 DB,会导致并发时缓存是旧值
可能的追问
- 先更新 DB 还是先删 Cache?(答:先更新 DB,再删 Cache)
- 延迟双删是什么?(答:删除 Cache 后延迟一段时间再删除一次,防止并发)
- 能做到强一致吗?(答:不能,只能做到最终一致,强一致需要分布式事务)
问题二:分布式 Session 如何实现?
回答思路
考察的是对分布式 Session 方案的理解。
- Session 共享问题:单机 Session 无法跨机器共享
- Spring Session + Redis:将 Session 存储到 Redis
- 核心原理:Filter 拦截请求,替换 HttpSession 实现
关键要点
- Session 存在 JVM 内存,集群环境下各节点不共享
- Spring Session 通过 Filter 将 Session 存入 Redis
- 使用
@EnableRedisHttpSession开启
可能的追问
- Session 数据序列化用什么?(答:推荐 JSON,避免 Java 序列化)
- Session 过期时间和 Redis TTL 怎么保持一致?(答:Spring Session 自动同步)
- Session 和 Token 哪个更好?(答:各有优劣,Session 有状态管理方便,Token 无状态扩展性好)
问题三:如何设计一个单点登录系统?
回答思路
考察的是对 CAS 原理的理解。
- SSO 定义:一次登录,多处访问
- CAS 流程:用户访问 A 系统 → 重定向到 CAS Server → 验证用户名密码 → 返回 ST → A 验证 ST
- 三个核心票据:TGT、TGC、ST
关键要点
- CAS Server 统一认证,各系统验证 Ticket
- ST 一次性使用,防止冒用
- TGC 存在浏览器 Cookie,TGT 存在 CAS Server
可能的追问
- CAS 和 OAuth2 的区别?(答:CAS 专注单点登录,OAuth2 支持授权)
- CAS 如何实现登出?(答:销毁 TGT,各系统收到通知清除 Session)
- CAS 的 ST 为什么设计成一次性的?(答:防止 ST 被截获后冒用)
问题四:如何实现接口幂等性?
回答思路
考察的是对幂等性实现的理解。
- 幂等性定义:多次执行结果一致
- 常用方案:Token 机制、唯一键、状态机
- Token 机制:提交前获取 Token,请求时携带 Token,服务端删除 Token
关键要点
- 插入操作:唯一键冲突捕获
- 更新操作:状态机 + 版本号
- 删除操作:天然幂等
- Token 机制:Redis 存储 Token,请求前获取,执行时校验并删除
可能的追问
- POST 请求怎么幂等?(答:Token 机制)
- 分布式锁能保证幂等吗?(答:能,但性能损耗大)
- 消息队列消费怎么幂等?(答:消息 ID + 业务去重表)
问题五:如何设计一个分布式任务调度系统?
回答思路
考察的是对分布式任务调度的理解。
- 分片模式:大任务拆分为多个小任务并行处理
- 防重复执行:分布式锁 + 状态检查
- 任务框架:ElasticJob、XXL-JOB
关键要点
- 分片策略:Hash 分片、范围分片
- 分布式锁:保证同一时刻只有一个节点执行
- 状态检查:乐观锁 + 状态更新
可能的追问
- 任务失败了怎么办?(答:重试机制 + 失败告警)
- 任务超时怎么处理?(答:超时监控 + 中断)
- 广播模式和分片模式的区别?(答:广播所有节点都执行,分片每个节点执行一部分)
问题六:如何实现全链路限流?
回答思路
考察的是对分层限流的理解。
- 限流层次:网关层 → 应用层 → 资源层
- 限流算法:滑动窗口、令牌桶、漏桶
- Sentinel 限流:注解 + 规则配置
关键要点
- 网关层:Nginx/Lua,限制总入口流量
- 应用层:Sentinel/Hystrix,限制接口 QPS
- 资源层:数据库连接池,限制数据库连接
可能的追问
- 滑动窗口和令牌桶的区别?(答:滑动窗口统计一段时间内请求数,令牌桶按固定速率放行)
- 限流后返回什么?(答:友好错误、兜底数据、排队)
- Sentinel 和 Hystrix 的区别?(答:Sentinel 是滑动窗口,Hystrix 是滚动窗口)
问题七:如何设计一个异地多活架构?
回答思路
考察的是对单元化架构的理解。
- 单元化:每个地域是独立单元,自包含
- 流量路由:按用户 ID 或地域路由
- 数据同步:单元内强一致,单元间最终一致
关键要点
- 单元内:分布式数据库,强一致
- 单元间:异步复制,最终一致
- 跨单元事务:TCC 或 Saga 模式
可能的追问
- 单元化架构的核心思想是什么?(答:每个单元自包含,数据和流量隔离)
- 如何处理跨单元事务?(答:TCC、Saga 或接受最终一致)
- 同城双活和异地多活的区别?(答:同城延迟低,异地可应对城市级别灾难)
问题八:如何处理缓存穿透、击穿、雪崩?
回答思路
考察的是对缓存问题的全面理解。
- 穿透:查询不存在的数据 → 布隆过滤器
- 击穿:热点 key 过期 → 互斥锁 / 逻辑过期
- 雪崩:大量 key 同时过期 → 过期时间随机化 + 熔断降级
关键要点
- 穿透:布隆过滤器快速判断 key 是否存在
- 击穿:互斥锁保证只有一个线程查 DB,逻辑过期不阻塞
- 雪崩:过期时间随机化 + 本地缓存兜底 + 熔断降级
可能的追问
- 布隆过滤器为什么不能删除?(答:删除会影响其他 key 的判断)
- 互斥锁和逻辑过期的区别?(答:互斥锁数据一致但有等待,逻辑过期无等待但可能返回脏数据)
- 如何选择降级策略?(答:根据业务容忍度决定)
问题九:如何实现分布式链路追踪?
回答思路
考察的是对 TraceId 机制的理解。
- TraceId:请求链路的唯一标识
- SpanId:每一步的编号
- MDC:Logback 集成 TraceId
关键要点
- TraceId 在网关生成,在整个链路中传递
- HTTP Header / RPC RpcContext / MQ 消息 Header 传递
- Logback MDC 将 TraceId 写入日志
可能的追问
- TraceId 怎么生成?(答:UUID 或 Snowflake)
- Skywalking 和 Zipkin 的区别?(答:Skywalking 功能更强,Zipkin 更轻量)
- 如何在日志中看到 TraceId?(答:Logback MDC 配置)
问题十:如何设计一个分库分表方案?
回答思路
考察的是对分库分表的理解。
- 分片键选择:选择分布均匀的字段
- ID 生成:号段模式或雪花算法
- 分片中间件:ShardingSphere、MyCat
关键要点
- 分片键:尽量选择 ID 或时间,避免热点
- ID 生成:号段模式批量取,雪花算法不依赖外部
- 分片后的问题:跨分片查询、分页
可能的追问
- 雪花算法时钟回拨怎么办?(答:等待、使用上一个 Sequence)
- 分库分表后如何做分页查询?(答:Scatter-Gather 并行查询所有分片)
- 分库分表后如何做跨库 JOIN?(答:绑定表广播、单库内 JOIN)
总结
分布式场景的面试题,本质上考察的是:
- 对问题的理解:能不能说清楚问题的本质
- 对方案的理解:能不能说清楚方案的原理和取舍
- 对细节的掌握:能不能说出实现的关键点
背答案是没有用的,理解原理才是关键。
