Skip to content

微服务与分布式系统面试题 ​

生成时间:2026-06-19 18:29 覆盖考点:DDD边界划分 / 注册中心健康检查 / BASE落地 / 服务端vs客户端负载均衡 / 配置灰度 / Leaf分布式ID / 服务雪崩 / 数据库拆分 / 链路追踪对比 / 千万级架构设计


【面试题】1. 领域驱动设计(DDD)里的"限界上下文"怎么指导微服务边界划分?举个例子说明 ​

【标准答案】限界上下文是DDD的核心概念,简单说就是一个领域模型有明确语义边界的范围——在这个范围里,同一个词有确定的含义。比如"订单"在交易上下文里关注价格和商品,在物流上下文里关注地址和配送状态,两个上下文里的"订单"是不同的模型。微服务边界的黄金法则:一个限界上下文对应一个微服务,不多不少。实际操作时先做事件风暴,识别出聚合、领域事件和限界上下文,然后按"高内聚低耦合"原则切割。如果两个上下文之间耦合太紧,先别急着拆,可能边界还没划对。关键是一旦拆了,跨上下文的通信只通过事件或API,绝不共享数据库。


【面试题】2. 注册中心的健康检查机制有哪几种模式?服务挂了注册中心怎么第一时间知道? ​

【标准答案】主要有三种模式。第一种是客户端心跳上报,Eureka和Nacos临时实例用的就是这种方式——服务每几秒发一次心跳,注册中心超时没收到就踢掉。第二种是服务端主动探测,Consul支持TCP/HTTP/gRPC健康检查,注册中心定期去调服务的健康端点,更准确但消耗更大。第三种是长连接断连感知,Nacos 2.x的gRPC协议下连接断开注册中心立刻知道,不需要等心跳超时。面试官最想听的是场景区分:心跳适合服务数多、资源敏感的场景,主动探测适合对健康状态要求严的,生产里常组合使用——心跳做存活检测,健康端点做就绪检测,探活和探就绪不是一个东西。


【面试题】3. BASE理论里"软状态"和"最终一致性"在真实项目中怎么落地?不是概念背诵 ​

【标准答案】"软状态"就是允许系统中的数据存在中间态,不用时刻一致。比如下单后订单从"已支付"到"已发货"有一个时间窗口,这个窗口里用户看到"已支付"是正常的,不需要立即变。最终一致性的落地靠异步消息:订单服务支付成功后发消息给库存服务扣库存,库存可能晚几秒才扣完,但一定会扣。工程上两个关键点:一是幂等,消息可能重发,库存服务用唯一键保证不重复扣;二是可监控,必须有对账任务每天确认"最终"到底一致了没——比如凌晨跑一次订单和库存的差异报表。BASE不是妥协,是在可用性和一致性之间做务实选择。


【面试题】4. Ribbon客户端负载均衡和Nginx服务端负载均衡各有什么优劣?实际项目怎么分层组合? ​

【标准答案】客户端负载均衡的负载逻辑跑在调用方进程里,绕过中心代理直连服务实例,优点是无单点、延迟低、和注册中心天然配合,缺点是每个客户端都要维护一份服务列表、改策略得重启。Nginx这类服务端负载均衡是中心化代理,所有流量先到Nginx再分发,优点是集中管控、改配置不重启,缺点是Nginx自己是单点和瓶颈。实际项目标准做法是组合:外层Nginx做接入层负载+高可用(Keepalived),扛南北向流量(外部用户→系统);内层微服务间用客户端负载均衡直连,扛东西向流量(服务→服务)。各司其职,互不干扰。


【面试题】5. 配置中心的灰度发布和紧急回滚怎么设计?Nacos里配置改错了怎么快速止血? ​

【标准答案】配置灰度发布核心是"先小范围验证再全量推送"。Nacos里用命名空间隔离——dev、staging、prod各自独立,先在staging验证再推prod。更精细的做法是用标签灰度:先把新配置发给打了特定标签的机器,观察指标没异常再全量。紧急回滚靠配置版本历史,Nacos每次变更都有记录,出问题直接点回滚到上一版本。但有个大坑:如果修改了多个Key,回滚时必须确保所有关联配置一起退回,否则不一致。建议把关联配置放同一个Data ID里统一管理。最关键的是——应用侧必须有配置兜底,Nacos挂了或返回异常值,至少用本地缓存的上一版配置继续跑,不能裸奔。


【面试题】6. 美团Leaf的号段模式和雪花模式各是怎么实现的?号段模式的双Buffer优化解决了什么痛点? ​

【标准答案】Leaf号段模式是从数据库批量取一段ID区间,比如一次拿1000个号,内存里用完再取下一段,数据库访问频率直接降了1000倍。雪花模式就是标准雪花算法,用ZK持久顺序节点分配WorkerID。双Buffer优化是号段模式的点睛之笔:号段快用完时(比如用了90%),异步启动线程去取下一段放到备用Buffer,号段耗尽后直接切换,毫秒级完成,ID生成不会卡顿。如果没有双Buffer,号段耗尽时取号是同步的,数据库随便抖一下业务就跟着抖。面试官想听的是你理解"空间换时间"和"预加载"思想——用一个Buffer的冗余去交换延迟的确定性。


【面试题】7. 服务雪崩的完整传播链条是什么?每一层分别用什么手段来阻断? ​

【标准答案】雪崩传播链:一个服务变慢 → 调用方线程池打满 → 调用方也变慢 → 它的上游又被拖垮 → 故障像多米诺骨牌一路向上蔓延。阻断分层打:第一层,超时控制——每个RPC必须设超时,不能让一个慢调用无限阻塞线程。第二层,熔断——下游错误率超阈值直接熔断,快速失败不等待。第三层,限流——入口处限制QPS,超过的直接拒绝,保护系统不被冲垮。第四层,线程池隔离——给不同下游分配独立线程池,一个挂了不霸占全部。第五层,降级——返回兜底数据,推荐挂了返回默认列表而不是白屏。五层纵深防御,面试官最爱听"不是靠单点手段,而是层层设防"。


【面试题】8. 微服务拆分中数据库怎么拆?分库之后跨库Join和分布式事务怎么解决? ​

【标准答案】数据库拆分底线是"一个微服务一个数据库",绝不让两个服务直连同一个库。跨库Join解法优先级:第一,应用层拼接——订单服务查订单,用户服务查用户,调用方拼结果。第二,数据冗余——用户头像昵称冗余一份到订单库,用最终一致性同步,读取时直接查本地表。第三,全局索引——用ES建只读宽表索引,跨库查询走ES。分布式事务尽量通过业务设计避免——能最终一致就别上强一致。如果真需要,转账场景用Seata AT或TCC,但记住都有性能代价。最好的分布式事务是"不需要分布式事务的设计"。


【面试题】9. Jaeger、Zipkin和SkyWalking三款链路追踪系统有什么区别?技术选型怎么决策? ​

【标准答案】Zipkin是鼻祖,架构简单,数据采集靠拦截器上报,纯追踪够用但缺乏指标分析。Jaeger是Uber开源的,兼容OpenTracing标准,支持自适应采样,和Kubernetes集成深,适合多语言异构+CNCF技术栈团队。SkyWalking是Apache项目,Java生态最友好,用字节码增强做零侵入采集,同时集成Tracing+Metrics+Logging三项能力,一个Agent全搞定。选型决策很简单:纯Java、想开箱即用、要可观测性一体化→SkyWalking;多语言、拥抱CNCF→Jaeger;轻量够用→Zipkin。国内绝大多数Java团队选SkyWalking,因为Agent挂上去就能用,改造成本几乎为零。


【面试题】10. 假如你当架构师,老板说要做支持千万级用户的微服务系统。从架构设计到上线运维,分几个阶段?每个阶段交付什么、核心决策是什么? ​

【标准答案】分六个阶段。第一阶段"定边界"——两周内输出领域模型和微服务拆分方案,控制在10个服务以内,交付服务蓝图和接口契约。第二阶段"搭骨架"——搭注册中心+配置中心+网关+链路追踪+CI/CD流水线,基础设施没搭完不写一行业务代码。第三阶段"啃骨头"——先做最核心的一两个服务(用户+订单),把技术栈、公共库、代码规范定型,后面照抄。第四阶段"铺功能"——并行开发剩余服务,引入消息队列解耦。第五阶段"压测加固"——全链路压测,加限流熔断、缓存、读写分离、分库分表。第六阶段"灰度上线"——先切1%真实流量观察三天,逐步放量到100%。核心决策:基础设施先行+核心服务立标杆——很多人上来就拆服务写代码,注册中心没搭好、监控没有、CI/CD没通,后面全是技术债。


本次10题覆盖考点:DDD边界划分 → 注册中心健康检查 → BASE落地 → 客户端vs服务端负载均衡 → 配置灰度 → Leaf分布式ID → 服务雪崩 → 数据库拆分 → 链路追踪对比 → 千万级架构设计

题型分布:概念题(1,3) | 原理题(2,7) | 方案对比题(4,6,9) | 架构设计题(5,8) | 场景面试题(10)

难度递进:基础(1-3) → 进阶(4-7) → 高阶架构(8-10)