1. 问题爆发:单体架构的极限
原来的订单系统长这样:
- 技术栈:SpringBoot + MyBatis + MySQL(主从)
- 部署:单机跑所有模块(订单、支付、库存)
- 痛点 :
- 接口响应慢:高峰期下单接口从200ms飙升到5s+
- 数据库扛不住 :订单表超过500万行,
order by create_time
直接OOM - 耦合严重:改库存逻辑居然要重启订单服务
结论:单体架构在业务早期确实快,但流量上来后就是灾难。
2. 技术选型:微服务还是垂直拆分?
面对性能瓶颈,考虑过两种方案:
方案 | 优点 | 缺点 |
---|---|---|
垂直拆分 | 改造成本低,风险小 | 治标不治本,扩展性差 |
微服务化 | 彻底解耦,独立伸缩 | 技术复杂度高,运维成本爆炸 |
最终选择 SpringCloud Alibaba,因为:
- 业务未来需要快速迭代(比如独立升级支付模块)
- 团队已有K8s集群,能解决微服务部署问题
3. 实战:订单系统的微服务改造
(1) 服务拆分
- 订单服务:核心下单逻辑,MySQL分库分表
- 支付服务:对接支付宝/微信,独立降级
- 库存服务:Redis缓存+异步扣减
(2) 引入关键组件
# Nacos 服务注册与配置中心
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
# Sentinel 流控熔断
feign:
sentinel:
enabled: true
(3) 分布式事务方案
放弃强一致,改用最终一致性:
-
下单流程 :
- 订单服务生成预订单(状态=待支付)
- 发MQ消息触发支付和库存预占
- 支付成功后更新订单状态
-
补偿机制 :
- 定时任务扫描"待支付超时"订单
- 调用库存服务释放预占库存
// 伪代码:下单入口
@Transactional
public void createOrder(OrderDTO orderDTO) {
// 1. 本地事务保存订单
orderMapper.insert(order);
// 2. 发MQ消息(保证本地事务成功后发送)
rocketMQTemplate.send("order-create-topic", order);
}
4. 性能对比
压测结果(单机 vs 微服务,并发1000):
指标 | 单体架构 | 微服务架构 |
---|---|---|
下单成功率 | 68%(超时崩) | 99%(自动降级) |
平均响应时间 | 4200ms | 800ms |
数据库QPS | 350(主库挂) | 50(分库分摊) |
代价:
- 运维复杂度↑:需要监控Nacos/Sentinel/Redis等10+组件
- 排错成本↑:一个下单问题可能涉及3个服务日志
5. 深度踩坑
- 分布式ID :雪花算法时钟回拨导致重复ID,改用美团Leaf
- Feign超时:默认1s不够,支付调银行接口要设10s,但需配合熔断
- 链路追踪:没加Sleuth时,排查跨服务调用像盲人摸象
总结:技术选型时要更多知其然
- 小团队慎用微服务:如果日活<10万,先优化单体(比如加缓存、异步化)
- 拆分原则:按业务边界拆分,避免"为微服务而微服务"
- 监控先行:Prometheus+Grafana+ELK全套安排上,否则线上就是黑洞