Java 真实面试专题

13 篇 · 免费在线阅读

微服务与分布式面试题精选

Java 后端真实面试专题 · 微服务与分布式篇

这一篇拉开中级和高级的差距。每题三段: ① 标准答(讲透:是什么+为什么+怎么做+原理)→ ② 拓展(成体系带出关联点和必追问的)→ ③ 怎么接到你自己的项目

年限标签:🟢 3年内 🔴 3年+


1. 🟢 SpringCloud 的核心组件有哪些,各解决什么问题?

标准答

  • 注册中心(Nacos/Eureka):服务注册与发现,解决"服务实例动态变化、调用方怎么找到它"。
  • 远程调用(OpenFeign):声明式 HTTP 调用,像调本地方法一样调远程。
  • 负载均衡(LoadBalancer/Ribbon):从多个实例中选一个调用。
  • 网关(Gateway):统一入口,做路由、鉴权、限流。
  • 熔断限流(Sentinel/Hystrix):防止故障扩散。
  • 配置中心(Nacos Config):集中管理配置、动态刷新。

拓展

  • 现在主流是 SpringCloud Alibaba(Nacos + Sentinel + Seata + Dubbo),比 Netflix 那套(Eureka/Hystrix 已停更)更常用。
  • 每个组件解决一个分布式带来的新问题,理解"为什么需要它"比记名字重要。
  • 组件不是越多越好:先画出调用链和故障边界,再决定是否引入注册、网关、配置、事务等基础设施;每个组件都要有超时、重试、降级和观测方案。
  • Spring Cloud 版本、Spring Boot 版本和 Alibaba BOM 要对齐,不能只看单个 starter 的版本号;升级时重点验证负载均衡、熔断和配置刷新行为。
  • 公共能力应尽量下沉到平台层,业务服务保留清晰的领域边界,避免把网关变成“万能业务服务”。

往项目引 ⭐:"我项目用的就是 Alibaba 全家桶:Nacos 做注册+配置、OpenFeign 调用、Gateway 网关、Sentinel 限流熔断、Seata 分布式事务——能把每个组件对应到项目里解决的具体问题。"


2. 🟢 注册中心的作用和原理?Nacos 和 Eureka 区别?

标准答:服务启动时把自己的地址注册到注册中心,调用方从注册中心拉取可用实例列表实现服务发现;靠心跳保活,实例宕机/下线会被剔除。

  • Eureka:AP 模型,只做注册发现,自我保护机制。
  • Nacos:支持 AP/CP 切换,自带配置中心,功能更全,是现在主流。

拓展

  • "服务怎么知道实例下线了?"——心跳超时剔除 + 主动下线通知,客户端定期拉取/推送更新列表。
  • "AP 和 CP 怎么选?"——服务发现要高可用(AP),允许短暂读到下线实例(有重试兜底);要强一致选 CP(如 Zookeeper)。
  • 客户端一般本地缓存实例列表,注册中心挂了短期也能调。
  • 注册中心的“注册”和“配置”是两类一致性问题:实例列表通常允许短暂陈旧,配置变更则要有版本、推送失败重试和回滚记录,不能混为一谈。
  • 心跳剔除存在误判窗口;客户端还要做健康检查、连接失败摘除和退避重试,否则注册中心已经更新,调用方仍可能打到失效实例。
  • Nacos 的 AP/CP 是按数据和场景选择,不是简单的产品标签;切换前要明确临时不可用、旧实例可见和脑裂风险。

往项目引 ⭐:"我项目服务多机部署,全靠 Nacos 动态发现——扩容新实例自动注册进来、调用方无感知。选 AP 模式,因为服务发现要的是高可用,短暂的实例信息不一致可接受、有 Feign 重试兜底。"


3. 🟢 OpenFeign 是什么?怎么做负载均衡和降级?

标准答:OpenFeign 是声明式 HTTP 客户端——定义一个接口加 @FeignClient 注解,调它的方法就等于发 HTTP 请求到对应服务,底层帮你拼请求、做负载均衡。负载均衡集成了 LoadBalancer,从注册中心拿实例列表轮询;降级配 fallback,下游挂了走兜底逻辑。

拓展

  • "Feign 怎么负载均衡?"——拿到服务名对应的实例列表,按策略(默认轮询)选一个。
  • "超时和重试?"——可配 connectTimeout/readTimeout,重试要幂等。
  • Feign 底层可换 OkHttp/HttpClient 连接池提升性能。
  • 连接超时、读取超时和整体调用预算要分开设置;下游调用链的总超时应小于上游接口超时,避免重试把延迟层层放大。
  • fallback 只能返回业务允许的兜底,不要把“下单失败”伪装成成功;最好区分降级、超时、业务 4xx 和网络 5xx 的处理策略。
  • 重试要限制次数并配指数退避、熔断和幂等键;非幂等 POST 默认不自动重试,避免重复扣款或创建订单。

往项目引 ⭐:"我项目服务间调用全用 Feign,配了超时和 fallback——下游挂了走降级返回兜底数据,不让调用方跟着一起超时崩溃。比手写 HttpClient 简洁太多。"


4. 🟢 网关的作用?请求怎么路由到具体服务?

标准答:网关是系统统一入口,承担路由转发、鉴权、限流、跨域、日志、灰度等。Gateway 工作原理:靠**断言(Predicate)匹配路由规则(按路径/header/参数),靠过滤器(Filter)**做处理(鉴权、限流、改写),再用 lb://服务名 经负载均衡转发到具体实例。

拓展

  • "Gateway 和 Zuul 区别?"——Gateway 基于 WebFlux 响应式、非阻塞、性能好;Zuul1 是阻塞式。
  • 过滤器分全局过滤器和路由过滤器,可自定义。
  • 网关是统一做横切的最佳位置(鉴权、限流别让每个服务各做一遍)。
  • 路由匹配要注意优先级和路径改写;鉴权失败、限流和下游异常都要返回统一错误码,并保留 traceId 方便排查。
  • 网关不应承载长耗时业务和大文件处理;上传下载可用专门的对象存储签名地址,避免占满网关连接。
  • 过滤器里的重试、跨域和鉴权要做幂等与超时控制,多个网关实例之间的限流计数需要共享存储或采用网关集群方案。

往项目引 ⭐:"我项目所有外部请求先过网关,统一做 token 校验、限流、跨域,后端微服务只管业务、不重复处理这些。还在网关做了灰度路由——按用户标签把部分流量导到新版本。"


5. 🟢 熔断、降级、限流分别是什么?

标准答

  • 限流:控制入口流量,超过阈值就拒绝/排队,保护系统不被打垮。
  • 熔断:下游故障率高时,快速失败、暂时不再调用它(像保险丝跳闸),过段时间半开放行少量请求试探,恢复了再闭合。防止故障扩散。
  • 降级:资源不足或出错时返回兜底数据/默认值,保证核心功能可用(有损服务)。

拓展

  • 三者关系:限流在入口、熔断在调用下游、降级是兜底结果,常一起用,Sentinel 都能做。
  • "熔断的三个状态?"——关闭(正常)、打开(快速失败)、半开(试探恢复)。
  • 降级要区分"自动降级"(熔断触发)和"手动降级"(开关)。
  • 限流阈值应按 QPS、并发数或系统负载设置,并给核心/非核心接口不同配额;单看平均流量会漏掉峰值和突发。
  • 熔断统计窗口、最小请求数和恢复探测间隔要结合业务延迟配置;窗口太短容易误触发,太长又反应迟钝。
  • 降级响应必须可观测(响应头/日志标记)并有恢复开关,不能长期静默返回旧数据;核心写操作通常选择快速失败而不是假成功。

往项目引 ⭐:"我项目大促时对非核心接口(推荐、排行)手动降级、对下单接口限流、对依赖的第三方做熔断,保证核心交易链路不被边缘功能拖垮——按重要性分级保护。"


6. 🔴 什么是服务雪崩?怎么避免?

标准答:一个服务故障/变慢,导致调用它的线程被占满阻塞,调用方也跟着故障,层层传导最终整个系统瘫痪,就是服务雪崩。根因是同步调用 + 资源(线程)耗尽。避免:熔断、降级、限流、超时控制资源隔离(不同依赖用不同线程池/信号量)。

拓展

  • "为什么隔离能防雪崩?"——一个慢依赖只耗尽自己那个线程池,不会拖垮整个服务的所有线程。
  • 超时一定要设,没有超时的同步调用是雪崩的温床。
  • Hystrix 用线程池隔离、Sentinel 用信号量隔离 + 熔断。
  • 先画依赖图并计算资源预算:每层的线程池、连接池、队列和超时都要有上限,不能只在最外层加一个熔断注解。
  • 重试与超时相乘会产生“重试风暴”;重试预算应小于请求剩余时间,并带随机抖动,必要时只在一个层级重试。
  • 故障演练要验证慢、拒绝、半开恢复和依赖恢复后的缓存/队列堆积,监控 P99、线程池队列长度和错误比例。

往项目引 ⭐:"我项目给不同下游调用做了线程池隔离 + Feign 超时 + Sentinel 熔断。演练过把某个下游故意拖慢,发现它只影响自己那条链路、没把整个服务拖垮——隔离 + 超时是防雪崩的关键。"


7. 🔴 分布式事务有哪些方案?怎么选?

标准答

  • Seata AT 模式:无侵入,框架自动生成回滚日志(before/after image),适合大多数场景。
  • TCC(Try-Confirm-Cancel):业务自己实现预留/确认/取消,强一致、性能好但改造成本高。
  • 本地消息表 / MQ 最终一致:靠消息保证最终一致,适合时效不敏感。
  • 最大努力通知:通知 + 重试,对账兜底。 选型看一致性要求和性能,能不用分布式事务就别用(先看能否用业务设计规避)。

拓展

  • "Seata AT 原理?"——一阶段本地事务提交并记录回滚日志,二阶段全局提交就删日志、全局回滚就用日志反向补偿。
  • TCC 要处理空回滚、悬挂、幂等。
  • 强一致 vs 最终一致是核心取舍。
  • 先尝试把跨服务写操作改成“单服务事务 + 事件最终一致”;分布式事务会增加锁持有时间、协调器依赖和故障恢复成本。
  • Seata AT 适合可逆的数据库更新,SQL 兼容性、回滚日志体积和长事务仍需压测;TCC 的 Try/Confirm/Cancel 必须幂等、可重入、可空回滚。
  • MQ/本地消息表要配投递状态、重试、死信和对账,明确业务可接受的最终一致时间,而不是笼统宣称“绝对一致”。

往项目引 ⭐:"我项目下单扣库存跨订单和库存两个服务,用 Seata AT 保证一致;积分这种不要紧的走 MQ 最终一致。按业务重要性分别选方案,不是一刀切上 Seata。"


8. 🔴 分布式 id 怎么生成?雪花算法的坑?

标准答:常用雪花算法(Snowflake)——64 位:1 符号位 + 41 位时间戳 + 10 位机器 id + 12 位序列号,趋势递增、有序、全局唯一、高性能、不依赖外部中间件。其他方案:Redis incr、号段模式(美团 Leaf)、UUID(无序不适合做主键)。

拓展

  • "雪花算法最大的坑?"——依赖机器时钟,时钟回拨会生成重复 id。解决:检测到回拨就等待、或抛异常、或用备用位。
  • "为什么不用 UUID?"——无序,做主键会导致 B+ 树页分裂、随机 IO。
  • 机器 id 怎么分配——可由 Nacos/Zookeeper 统一分配避免冲突。
  • 41 位时间戳的可用年限取决于自定义起始时间,10 位机器位和 12 位序列位也可按部署规模重新切分;要把位布局、起始时间和溢出策略写进协议文档。
  • 时钟回拨时“等待”会牺牲可用性,“抛异常”会造成请求失败;生产上还要监控 NTP、机器 id 冲突和序列耗尽,并准备数据库/号段兜底。
  • ID 趋势递增不等于严格连续,不能用它推断业务数量或权限;对外暴露时可增加不可猜测的业务编号。

往项目引 ⭐:"我项目分库分表后主键用雪花算法,既全局唯一又趋势递增、对聚簇索引友好。我们还处理了时钟回拨——检测到回拨小范围就等待、大范围就告警,避免生成重复 id。"


9. 🟢 接口幂等怎么保证?(结合下单)

标准答:幂等指同一请求执行多次结果一致。手段:

  • 唯一索引:如订单号唯一,重复插入直接失败。
  • token 机制:进页面发 token,提交时校验并删除(用一次),重复提交第二次失败。
  • 状态机:只允许特定状态流转,重复操作被状态拦住。
  • 分布式锁 / select for update

拓展

  • GET、DELETE 天然幂等,POST 要重点防(重复提交、网络重试、MQ 重复消费)。
  • token 校验 + 删除要原子(Redis Lua)。
  • 幂等和防重复提交、消息幂等是一类问题。
  • 幂等键应覆盖业务主体和关键参数,服务端保存“处理中/成功/失败”状态与结果;请求超时重试时返回原结果,不重新执行副作用。
  • Redis token 只是第一道防线,数据库唯一索引、状态机条件更新(where status = ?)和支付方流水号必须兜底。
  • 跨服务幂等要把幂等键透传到 MQ/下游,并设置合理保留期;过早清理会让迟到的重试再次产生副作用。

往项目引 ⭐:"我项目下单接口用 token + 唯一订单号双保险——进结算页发一个 Redis token,提交时用 Lua 原子校验删除,再加订单号唯一索引兜底。前端重复点、网络重试都只会成功一笔。"


10. 🟢 常见限流算法有哪些?

标准答

  • 固定窗口计数:单位时间内计数,超了拒绝。简单但有临界突刺(窗口交界瞬时双倍)。
  • 滑动窗口:把窗口细分,平滑很多。
  • 漏桶:请求进桶、以恒定速率流出,强制平滑、不允许突发。
  • 令牌桶:定速生成令牌、请求取令牌才放行,允许一定突发,最常用。

拓展

  • 令牌桶和漏桶区别:令牌桶允许突发、漏桶严格匀速。
  • 成熟实现:Sentinel、Guava RateLimiter、Redis + Lua。
  • 单机限流 vs 分布式限流(用 Redis 共享计数)。
  • 固定窗口适合粗粒度保护,滑动窗口/令牌桶适合更平滑的接口;算法还要考虑公平性、突发容量和时钟精度。
  • 分布式限流的 Redis 计数要保证过期和原子递增,集群跨槽时可按业务 key 设计;网络故障时要明确 fail-open 还是 fail-closed。
  • 限流不是排队:超限请求是快速失败、排队还是降级,要依据接口是否可重试和用户体验决定,并监控拒绝率。

往项目引 ⭐:"我项目网关用 Sentinel 做 QPS 限流(令牌桶,允许合理突发),秒杀接口单独配更严的规则防刷,短信接口用 Redis 滑动窗口按手机号限流。按场景选算法。"


11. 🟢 CAP 理论是什么?

标准答:分布式系统三者最多同时满足两个——一致性 C(所有节点同一时刻数据一致)、可用性 A(每个请求都有响应)、分区容错性 P(网络分区时系统仍能工作)。由于网络分区不可避免(P 必选),实际是在 C 和 A 之间权衡

拓展

  • CP 例子:Zookeeper(选主期间不可用、保一致)。
  • AP 例子:Eureka、Nacos 默认(保可用、可能读到旧数据)。
  • CAP 是粗粒度的,实际系统往往是局部 CP、局部 AP。
  • CAP 讨论的是发生网络分区时的取舍;没有分区时系统可以同时表现出较强一致和可用,不能简单说任何系统“永远只能二选一”。
  • 一致性还要说明语义(线性一致、顺序一致、最终一致)和范围(单 key、单分区还是跨服务),否则 C 的含义过于宽泛。
  • 选型时把业务动作分级:注册发现可以接受短暂旧列表,余额扣减通常需要更强的写一致和明确的失败反馈。

往项目引 ⭐:"我项目注册中心选 Nacos 的 AP 模式——服务发现要高可用,短暂的实例信息不一致可以接受(有重试)。而涉及钱的配置我们就要强一致。这就是按场景在 CA 间权衡。"


12. 🔴 BASE 理论是什么?和 CAP 什么关系?

标准答:BASE 是对 CAP 中 AP 的延伸落地——基本可用(Basically Available)软状态(Soft State,允许中间状态)最终一致(Eventually Consistent)。核心思想是牺牲强一致换可用,允许数据有中间不一致状态,但最终会达成一致。

拓展

  • 是大多数互联网分布式系统的实际指导思想。
  • 分布式事务的"MQ 最终一致"就是 BASE 的体现。
  • "基本可用"——故障时降级、限流,保证核心可用而非全或无。
  • “软状态”不是无规则的脏数据,而是允许在收敛过程中存在可解释的中间状态;必须定义收敛触发器、最大延迟和冲突解决规则。
  • 最终一致方案要配补偿、幂等、对账和告警,不能只依赖“消息最终会到”;关键数据还要支持人工重放和审计。
  • 对用户展示时可用“处理中/稍后刷新”等状态承接短暂不一致,避免把技术延迟伪装成成功。

往项目引 ⭐:"我项目积分、消息、统计这些不要求实时一致的,都按 BASE 做最终一致——用 MQ 异步处理 + 定时对账兜底,体验和性能都更好。强一致只留给账户余额这种。"


13. 🔴 分布式锁有哪几种实现?怎么选?

标准答

  • Redisset nx ex + Lua 解锁,Redisson 看门狗续期):性能高,主流选择;主从切换可能丢锁,极端一致用 RedLock。
  • Zookeeper(临时顺序节点 + watch):可靠性高(节点宕机锁自动释放),性能略低于 Redis。
  • 数据库(唯一索引/for update):简单但性能差、不推荐高并发。 选择:高性能选 Redis、高可靠选 ZK。

拓展

  • "Redis 锁的看门狗?"——Redisson 后台线程定期续期,避免业务没跑完锁过期。
  • "ZK 为什么可靠?"——临时节点,持锁客户端断连节点自动删除、锁自动释放、且能 watch 前一个节点避免惊群。
  • Redis SET NX EX 的 value 必须包含持有者唯一标识,解锁时用 Lua 比较后删除;不要直接 DEL 别人的锁。锁的租期要覆盖业务或配可靠续期。
  • Redis 主从异步复制存在故障切换丢锁窗口,RedLock 也不能替代业务幂等和 fencing token;对金融级互斥要让资源端校验递增令牌。
  • ZK 临时顺序节点要只 watch 前驱节点,避免所有等待者同时唤醒;数据库锁要配索引和短事务,防止锁升级、长事务和连接池耗尽。

往项目引 ⭐:"我项目定时任务防并发用 Redisson 分布式锁,看中它的看门狗自动续期——长任务不怕锁提前过期。对可靠性要求极高的少数场景才考虑 ZK。"


14. 🟢 微服务怎么拆分?拆分原则?

标准答:按业务领域拆(DDD 限界上下文)、单一职责、高内聚低耦合、参考团队结构和迭代频率。常见:用户、订单、商品、支付、库存各成服务。

拓展

  • 别一上来就拆太细——过度拆分带来分布式复杂度(调用、事务、运维成本暴涨)。
  • 推荐"从单体演进、按痛点拆",先单体跑起来、瓶颈出现再拆。
  • 拆分要让大多数操作落在单个服务内,减少跨服务调用。
  • 拆分前先量化边界:数据所有权、发布频率、团队责任、独立扩容需求和故障隔离收益;只按数据库表名拆通常会制造大量同步调用。
  • 每个服务要拥有自己的数据写入口,跨服务读通过 API/事件完成;共享数据库只能作为迁移过渡,并记录清理计划。
  • 先建立契约测试、版本兼容和可观测性,再拆生产流量;否则“代码拆开了”却无法独立交付。

往项目引 ⭐:"我项目按业务域拆成订单、商品、库存、用户几个服务,公共能力(鉴权、限流)下沉到网关,没有为微服务而微服务——是业务和团队大了、单体迭代互相影响才拆的。"


15. 🟢 微服务和单体架构各有什么优缺点?

标准答

  • 单体:开发部署简单、调用快、易调试;但代码耦合、扩展只能整体扩、一处故障可能影响全局、技术栈固化。
  • 微服务:独立部署/扩展、故障隔离、技术栈灵活、利于多团队并行;但有分布式复杂度(远程调用、分布式事务、链路追踪、运维成本)。

拓展

  • 小团队/项目初期适合单体(别过度设计),业务和团队变大再拆。
  • 还有"模块化单体"作为中间过渡。
  • 比较架构时要看交付速度、故障半径、运维成熟度和成本,而不只是 QPS;微服务的网络、序列化和治理开销可能抵消独立扩展收益。
  • 模块化单体要求模块间禁止随意访问内部类/表,先建立边界,未来拆分才不会一次性重写。
  • 采用微服务后要补齐 CI/CD、配置、日志、链路、告警和容量管理,否则复杂度只是从代码转移到运维。

往项目引 ⭐:"我项目早期是单体、快速验证业务,用户和订单量上来、团队变大后才按域拆成微服务,能针对订单这种热点服务单独扩容——是按阶段演进的,不是盲目追新。"


16. 🟢 配置中心解决什么问题?

标准答:集中管理各服务、各环境的配置,支持动态刷新(改了配置不用重启服务)。如 Nacos Config、Apollo。

拓展

  • 配合 @RefreshScope 实现 Bean 配置热更新。
  • 敏感配置要加密存储。
  • 解决了"配置散落各服务、改一个要重启一片"的痛点。
  • 配置发布要有版本、审批、灰度和回滚;动态刷新不应直接修改不可变基础设施或正在执行事务的关键参数。
  • 读取配置失败时区分启动失败与继续使用最后已知版本,敏感配置要通过 KMS/密钥服务解密并避免写入日志。
  • 配置中心本身要高可用,客户端本地缓存和长轮询断线重连要有上限,避免中心抖动时形成连接风暴。

往项目引 ⭐:"我项目把限流阈值、功能开关、第三方参数放 Nacos 配置中心,大促时动态调限流阈值立即生效、不用重启服务,应急响应快很多。"


17. 🔴 链路追踪是什么?为什么微服务需要?

标准答:微服务里一个请求跨多个服务,出问题难定位"慢在哪、错在哪"。链路追踪(SkyWalking、Sleuth + Zipkin)给每个请求一个全局 traceId,每段调用一个 spanId,串起整条调用链,能看到每段耗时和报错点。

拓展

  • traceId 通过请求头在服务间透传,日志里打上 traceId 就能聚合一次请求的全部日志。
  • 还能看服务依赖拓扑、慢调用排行。
  • 是微服务可观测性(日志 + 链路 + 监控指标)的一部分。
  • 采样要按错误、慢请求和关键业务提高比例,不能为了省成本把所有异常采掉;traceId 还要与日志、指标和消息 headers 关联。
  • span 中避免记录密码、token 和完整身份证号等敏感数据;跨线程、异步和批处理要显式传递上下文并防止线程池污染。
  • 看到“总耗时很长”要区分排队、网络、序列化、数据库和下游业务耗时,链路追踪不是性能优化本身。

往项目引 ⭐:"我项目接了 SkyWalking,线上接口慢能直接看到是哪个下游服务、哪条 SQL 拖的,配合日志里的 traceId 快速串起整条请求——排查效率比一个个服务翻日志高太多。"


18. 🟢 服务间通信用 RPC 还是 HTTP?

标准答

  • HTTP(如 Feign):通用、跨语言、调试方便(Postman 就能测)、可读性好,但有 HTTP 头开销。
  • RPC(如 Dubbo、gRPC):二进制协议、性能高、适合内部高频调用,但跨语言和调试稍麻烦。 SpringCloud 体系多用 HTTP/Feign,性能敏感的内部调用可选 RPC。

拓展

  • "Feign 本质也是 HTTP?"——是的,声明式封装了 HTTP 调用。
  • gRPC 基于 HTTP/2 + Protobuf,性能和跨语言都不错。
  • 对外接口用 HTTP/REST,内部高性能链路评估 RPC。
  • 选 RPC 还是 HTTP 要同时看契约治理、流式能力、超时重试、可观测性、跨语言和团队调试成本;“二进制一定更快”不代表端到端一定更快。
  • 无论协议,都要定义版本兼容(字段可选、向后兼容)、错误码、超时和幂等语义;不要把网络异常当成业务失败重试。
  • 大文件、长连接和实时推送应单独评估协议,不要强行套短请求 RPC。

往项目引 ⭐:"我项目内部服务用 Feign(HTTP)够用且调试方便;对延迟特别敏感的核心链路评估过 Dubbo,但综合维护成本和团队熟悉度,最终还是用了 Feign——选型也要考虑团队和维护性。"


19. 🔴 一致性哈希是什么?解决什么问题?

标准答:把节点和数据都用哈希映射到一个 0~2³² 的环上,数据存到顺时针遇到的第一个节点。好处是增删节点时只影响环上相邻的一小段数据,避免普通取模(hash % N)在节点数变化时几乎所有数据都要重新映射、大面积迁移/缓存失效。

拓展

  • "数据倾斜怎么办?"——引入虚拟节点,每个物理节点对应多个虚拟节点均匀分布,避免数据集中。
  • 常用于分布式缓存、负载均衡、分库分表。
  • Redis Cluster 用的是哈希槽(固定 16384 槽),是另一种思路。
  • 一致性哈希只解决“节点变化时的映射范围”,不自动解决副本、一致性、热点和迁移期间读写;迁移要有双读/双写、校验和回滚策略。
  • 虚拟节点数量要结合 key 分布压测,节点权重变化时也要重新评估;热点 key 仍可能集中在一个节点,需要复制或本地缓存。
  • Redis Cluster 的 hash tag({user:1})可让相关 key 落在同一槽,但跨槽事务/MGET 仍受限制。

往项目引 ⭐:"我项目缓存分片用一致性哈希 + 虚拟节点,扩容加节点时只迁移一小部分 key,不会像取模那样导致缓存大面积失效、瞬间把 DB 打垮。"


20. 🔴 灰度发布怎么做?

标准答:新版本先发给一小部分流量/用户验证,没问题再逐步放量、最终全量。实现靠网关按规则路由——把带特定标签(用户 id、地域、header、内部员工)的请求导到新版本实例,其余走老版本。配合监控,出问题快速回滚。

拓展

  • 相关概念:蓝绿部署(两套环境切换)、金丝雀发布(小流量试探)。
  • 灰度要有数据隔离/兼容考虑,避免新老版本数据结构冲突。
  • 服务实例打标签 + 网关/负载均衡按标签路由是核心机制。
  • 放量指标要同时看错误率、P95/P99、业务转化和资源水位,设置自动暂停阈值;只看 HTTP 200 可能漏掉业务错误。
  • 新旧版本共享数据库时采用“先加字段、兼容读写、再切流、最后删字段”的演进顺序,避免回滚时旧版本无法解析新数据。
  • 灰度期间要保证同一用户/订单尽量粘到同一版本,消息消费者也要按版本兼容;回滚不等于数据回滚,需准备补偿脚本。

往项目引 ⭐:"我项目发新版本先灰度 5% 流量——网关按用户标签把这部分导到新版本实例,盯着监控(错误率、耗时)没问题再逐步放到 100%。出问题就把流量切回老版本,降低上线风险。"


你能答到第几层?

  • 三段都能答、还能往项目引:分布式这块你就是面试里的高级候选人。
  • 标准答 + 拓展能成体系答:知识够,差把它接到项目讲出来。
  • 标准答都磕巴:分布式概念多但成体系(注册/调用/网关/容错/事务/一致性),跟着主线 + 一个真实微服务项目就懂了。

这是面试专题的「微服务与分布式篇」,网站上还有并发、MySQL、Redis、Spring、项目场景等系统整理。 🌐 更多真实面试专题与资料:smallredtech.com 💬 想系统学 / 简历与辅导咨询,加微信:Ahongbb666(备注「面试题」)