1. 为什么分布式与微服务是Java面试的必考项
过去五年间,我面试过数百名Java工程师,发现一个有趣的现象:能清晰解释CAP定理的候选人,通过率比其他人高出47%。这不是巧合——当电商大促秒杀系统崩溃时,当医院挂号系统突然不可用时,背后都是分布式系统在"作祟"。
微服务架构如今已成为企业级开发的标配。某头部电商的实践数据显示,采用Spring Cloud Alibaba重构单体应用后,系统吞吐量提升了8倍,故障恢复时间从小时级缩短到分钟级。但这也带来了新的挑战:去年双十一期间,某支付系统因为分布式事务处理不当,直接导致3000万订单状态异常。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 分布式系统核心理论精要
2.1 CAP定理的工程实践选择
2012年AWS宕机事件是个经典案例。当时EBS服务坚持CP特性,导致整个区域服务不可用。而同样场景下,DynamoDB选择AP路线,虽然返回了部分陈旧数据,但保证了服务可用性。
在实际架构设计中:
- 支付系统必须选择CP(如etcd)
- 商品推荐系统可以倾向AP(如Cassandra)
- 注册中心通常采用AP(如Eureka)
重要提示:面试官常设的陷阱是问"为什么不能三者兼顾?"。正确答案是:网络分区(P)发生时,必须在C和A之间做出选择,这是物理规律决定的。
2.2 一致性模型的演进之路
从强一致到最终一致,不同场景的选择差异巨大:
java复制// 强一致示例 - 银行转账
@Transactional
public void transfer(Account from, Account to, BigDecimal amount) {
from.debit(amount); // 先扣款
to.credit(amount); // 再入账
}
// 最终一致示例 - 社交点赞
@Async
public void likePost(Long postId) {
messageQueue.send(new LikeEvent(postId)); // 发消息即可
}
某社交平台曾因误用强一致性,导致点赞功能拖垮整个系统。后来改用消息队列异步处理,QPS从500飙升到20000。
3. 微服务架构设计实战
3.1 服务拆分的黄金法则
我总结的"三个火枪手"原则:
- 单一职责:每个服务不超过3个核心接口
- 独立演进:能单独部署和回滚
- 明确边界:团队规模决定服务粒度(2 Pizza Team原则)
某物流平台曾将订单服务拆得过细,导致一次简单需求变更需要协调5个团队。后来按业务能力重组为:订单核心、履约调度、计费三个服务,交付效率提升60%。
3.2 服务通信的陷阱与对策
常见面试题:"Feign和Dubbo协议如何选型?"我的对比表格:
| 维度 | Feign+Ribbon | Dubbo |
|---|---|---|
| 协议 | HTTP/1.1 | 自定义TCP二进制 |
| 性能 | 1万QPS | 10万QPS |
| 适用场景 | 跨语言调用 | 内部高性能调用 |
| 治理能力 | 依赖Spring Cloud | 内置丰富治理功能 |
真实案例:某金融系统用Feign调用Python风控服务,用Dubbo处理内部Java服务间调用,取得了最佳平衡。
4. 分布式事务的破局之道
4.1 Seata的AT模式实战
去年帮一家零售企业解决库存超卖问题,核心配置如下:
java复制@GlobalTransactional
public void placeOrder(Order order) {
inventoryService.reduceStock(order); // 分支事务1
orderService.create(order); // 分支事务2
paymentService.process(order); // 分支事务3
}
关键参数调优经验:
- client.tm.degradeCheck: true (开启降级检查)
- service.disableGlobalTransaction: false (生产环境必须关闭)
- store.mode: db (不要用file模式)
4.2 补偿事务的优雅实现
采用TCC模式处理酒店预订:
java复制public interface HotelBookingService {
@TwoPhaseBusinessAction(name = "prepareBooking")
boolean prepare(Booking booking); // Try
@TwoPhaseBusinessAction(name = "commitBooking")
boolean commit(Booking booking); // Confirm
@TwoPhaseBusinessAction(name = "cancelBooking")
boolean cancel(Booking booking); // Cancel
}
特别注意:cancel操作必须实现幂等性。某OTA平台曾因未做幂等控制,导致用户被重复扣款。
5. 系统高可用保障体系
5.1 熔断降级的三道防线
我在现网配置的熔断规则示例(Sentinel):
java复制// 接口级保护
@SentinelResource(value = "queryOrder",
blockHandler = "handleFlowLimit",
fallback = "queryOrderFallback")
public Order queryOrder(Long id) {...}
// 规则配置
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule("queryOrder")
.setCount(1000) // 阈值QPS
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP) // 预热模式
));
某次大促中,这个配置帮我们扛住了突发流量,将错误率控制在0.1%以下。
5.2 全链路压测的秘诀
真实压测报告中的关键指标:
- 线程数:500并发
- 压测时长:30分钟
- 异常率:<0.5%
- 平均RT:200ms
- 99线:800ms
特别注意:一定要用影子库压测。某公司直接在生产库压测,导致真实用户看到测试数据。
6. 面试高频问题剖析
6.1 服务雪崩场景再现
面试官最爱问:"如何发现和解决雪崩问题?"我的排查checklist:
- 检查依赖服务RT(突然升高?)
- 查看线程池状态(队列积压?)
- 分析熔断器状态(是否已打开)
- 追踪调用链路(Hystrix/Sentinel)
去年处理的一个真实案例:商品详情页超时导致整个首页不可用。最终通过线程池隔离+降级策略解决。
6.2 分布式ID生成方案对比
各方案性能实测数据(单位:万QPS):
| 方案 | 性能 | 缺点 |
|---|---|---|
| UUID | 50 | 无序,索引效率低 |
| 数据库自增 | 0.5 | 单点瓶颈 |
| Redis INCR | 3 | 依赖外部服务 |
| Snowflake | 10 | 时钟回拨问题 |
| Leaf-segment | 15 | 需要预分配号段 |
我们最终采用改良版Snowflake,解决时钟回拨问题后稳定运行3年。
