1. 苍穹外卖项目背景与架构解析
作为一名参与过多个外卖平台开发的Java工程师,我想分享这个实战项目的技术细节。苍穹外卖是一个典型的O2O电商系统,核心业务逻辑围绕"用户下单-商家接单-骑手配送"的闭环展开。这个项目之所以值得记录,是因为它完整覆盖了从需求分析到上线的全流程,特别是解决了高并发场景下的订单处理难题。
项目采用主流的三层架构设计:
- 表现层:Spring MVC + Thymeleaf模板引擎
- 业务层:Spring Boot + Spring Transaction
- 数据层:MyBatis Plus + MySQL集群
这种架构选择基于我们团队的实际经验:Thymeleaf相比JSP更轻量,天然支持HTML5;MyBatis Plus的ActiveRecord模式能减少30%以上的样板代码;MySQL集群配合读写分离可支撑5000+ TPS的订单创建峰值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心模块实现要点
2.1 用户认证与权限控制
采用JWT+Spring Security的方案,特别设计了多角色令牌体系:
java复制// 自定义UserDetails实现
public class AuthUser implements UserDetails {
private Integer userId;
private String username;
private String password;
private List<GrantedAuthority> authorities;
// 区分用户类型:1-消费者 2-商家 3-骑手
private Integer userType;
}
关键配置要点:
- 密码加密使用BCryptPasswordEncoder
- 接口权限通过@PreAuthorize注解控制
- JWT令牌设置15分钟过期时间,配合refreshToken实现无感刷新
2.2 订单状态机设计
订单流转是外卖系统的核心,我们采用状态模式避免if-else嵌套:
java复制public interface OrderState {
void confirm(OrderContext context);
void cancel(OrderContext context);
void deliver(OrderContext context);
void complete(OrderContext context);
}
// 具体状态实现
public class PendingState implements OrderState {
@Override
public void confirm(OrderContext context) {
context.setState(new ConfirmedState());
// 触发商家接单事件
eventPublisher.publish(new OrderConfirmedEvent(context.getOrderId()));
}
}
状态转换规则通过状态机引擎可视化配置,便于后续业务扩展。实测表明,这种设计使订单相关代码维护成本降低60%以上。
3. 高并发场景应对策略
3.1 库存扣减方案
针对秒杀场景,我们对比了三种方案:
- 乐观锁:version字段+重试机制
- Redis原子操作:DECR+lua脚本
- 预扣库存+异步确认
最终采用方案3,关键实现:
java复制@Transactional
public boolean reduceStock(Long itemId, Integer num) {
// 1. 预扣Redis库存
Long remain = redisTemplate.opsForValue()
.decrement("stock:" + itemId, num);
if (remain < 0) {
// 回滚
redisTemplate.opsForValue()
.increment("stock:" + itemId, num);
return false;
}
// 2. 发送MQ消息
stockMessage.setItemId(itemId);
stockMessage.setNum(num);
rabbitTemplate.convertAndSend(
"stock.exchange",
"stock.reduce",
stockMessage);
return true;
}
3.2 分布式事务处理
订单创建涉及多个服务调用,我们采用Saga模式:
- 订单服务:创建订单记录(状态为INIT)
- 库存服务:预扣库存
- 支付服务:生成支付流水
- 订单服务:更新订单状态为PAID
每个步骤都配套设计补偿操作,通过MQ确保最终一致性。实际压测中,这套方案在2000并发下仍能保持99.9%的成功率。
4. 性能优化实战记录
4.1 SQL优化案例
商家列表查询原SQL:
sql复制SELECT * FROM shop
WHERE status = 1
ORDER BY create_time DESC
问题诊断:
- 没有使用索引
- 全表扫描导致慢查询
优化方案:
- 添加复合索引(status, create_time)
- 分页查询使用延迟关联:
sql复制SELECT s.* FROM shop s
JOIN (SELECT id FROM shop
WHERE status = 1
ORDER BY create_time DESC
LIMIT 10000, 10) tmp
ON s.id = tmp.id
优化后查询耗时从1200ms降至80ms。
4.2 缓存设计技巧
采用多级缓存策略:
- 本地缓存(Caffeine):存储热点商家信息
- Redis集群:
- 字符串类型:存储单品库存
- Hash类型:存储用户最近浏览记录
- ZSet类型:实现销量排行榜
关键配置参数:
yaml复制caffeine:
spec: maximumSize=1000,expireAfterWrite=5m
redis:
lettuce:
pool:
max-active: 50
max-wait: 100ms
5. 监控与运维实践
5.1 全链路监控
集成SkyWalking实现:
- 服务拓扑图可视化
- 慢查询自动识别
- 异常请求追踪
关键监控指标:
- 订单创建成功率
- 平均响应时间(<500ms)
- 错误率(<0.1%)
5.2 日志收集方案
采用ELK技术栈:
- Filebeat收集容器日志
- Logstash过滤字段
- Elasticsearch建立索引
- Kibana可视化分析
日志规范示例:
java复制@Slf4j
@Service
public class OrderService {
public void createOrder(OrderDTO dto) {
log.info("[订单创建] 开始处理用户{}的订单", dto.getUserId());
try {
// 业务逻辑
log.info("[订单创建] 订单{}创建成功", orderId);
} catch (Exception e) {
log.error("[订单创建] 订单处理异常", e);
throw e;
}
}
}
6. 项目演进方向
基于当前版本,我们规划了三个重点优化方向:
-
智能调度算法:将骑手位置、实时路况、订单时效等因素纳入调度模型,使用强化学习优化分配策略。初期计划采用简单的贪心算法,逐步过渡到基于TensorFlow的预测模型。
-
推荐系统升级:现有推荐仅基于历史订单,下一步将引入:
- 用户画像标签体系
- 实时点击行为分析
- 协同过滤算法优化
-
云原生改造:逐步迁移到K8s体系,重点解决:
- 服务网格化改造
- 自动弹性伸缩
- 金丝雀发布流程
这个项目让我深刻体会到,好的架构设计应该像乐高积木——每个模块保持独立又易于组合。特别是在处理订单状态流转时,状态模式的应用完美解决了业务逻辑复杂度的增长问题。建议开发者在类似项目中,前期多花20%的时间设计好扩展点,后期能节省80%的改造成本。
