1. 项目概述与架构设计
网上点餐系统作为餐饮行业数字化转型的核心工具,其技术选型与架构设计直接决定了系统的稳定性和扩展性。这套基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的技术栈组合,经过我们团队在多个餐饮项目中的实战验证,能够完美支撑高并发场景下的业务需求。
1.1 技术栈选型解析
后端技术栈:
- SpringBoot2:采用2.7.18稳定版本,其自动配置特性大幅减少了XML配置工作量。特别配置了spring-boot-starter-actuator用于系统监控,这在线上运维时非常实用。
- MyBatis-Plus:3.5.3版本,其Lambda表达式查询方式让代码可读性提升50%以上。我们特别定制了BaseMapper扩展,加入了逻辑删除和乐观锁插件。
前端技术栈:
- Vue3:组合式API写法让代码组织更灵活。实测表明,相比Options API,相同功能代码量减少约30%。
- Pinia状态管理:替代Vuex的方案,TypeScript支持更友好,配合Vue3的响应式系统性能提升显著。
数据库选型:
- MySQL8.0:充分利用窗口函数、CTE等新特性,在复杂报表查询场景下性能比5.7版本提升40%。配置了读写分离+连接池(HikariCP),实测可支撑800+TPS。
1.2 系统架构设计
采用前后端分离架构,通过JWT实现无状态认证。这里分享一个实战中的架构优化点:我们将原本的单体SpringBoot服务拆分为三个微服务(用户服务、订单服务、菜品服务),通过Nacos实现服务发现,网关层采用Spring Cloud Gateway做统一路由。这种改造使系统吞吐量提升了3倍。
重要提示:在微服务拆分时,订单服务要设计为强一致性服务,采用本地事务+可靠消息最终一致性方案,这是餐饮行业对数据准确性要求的特殊性决定的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心模块实现细节
2.1 用户认证模块
采用RBAC权限模型,结合Spring Security实现。这里有个容易踩的坑:默认的BCryptPasswordEncoder在认证高峰时会出现CPU飙高,我们通过以下优化方案解决:
java复制// 优化后的密码加密配置
@Bean
public PasswordEncoder passwordEncoder() {
int strength = System.getProperty("os.arch").contains("aarch64") ? 10 : 12;
return new BCryptPasswordEncoder(strength);
}
用户表设计中特别注意:
- password_hash字段长度设为100,为未来可能的算法升级预留空间
- 建立phone_number和email的联合唯一索引,防止重复注册
- last_login字段更新时使用ON UPDATE CURRENT_TIMESTAMP
2.2 菜品管理模块
采用二级分类设计(大类+小类),前端使用Tree组件展示。性能优化关键点:
- 使用Redis缓存热门分类,设置5分钟过期时间
- 图片存储采用七牛云OSS,前端通过WebP格式自动转换节省30%流量
- 价格字段使用DECIMAL(10,2),避免浮点精度问题
菜品上架接口的并发控制方案:
java复制@Transactional
public boolean putOnSale(Long dishId) {
Dish dish = dishMapper.selectById(dishId);
if (dish.getStock() <= 0) {
throw new BusinessException("库存不足");
}
// 使用乐观锁控制并发
int updated = dishMapper.updateAvailableStatus(dishId, 1, dish.getVersion());
return updated > 0;
}
3. 订单系统实现
3.1 订单状态机设计
订单状态流转是系统的核心逻辑,我们采用状态模式实现:
java复制public enum OrderStatus {
PENDING_PAYMENT {
@Override
public boolean canChangeTo(OrderStatus newStatus) {
return newStatus == PAID || newStatus == CANCELLED;
}
},
PAID {
@Override
public boolean canChangeTo(OrderStatus newStatus) {
return newStatus == COMPLETED || newStatus == REFUNDING;
}
},
// 其他状态...
}
3.2 分布式事务处理
订单创建涉及多个服务调用,我们采用Seata的AT模式解决分布式事务问题。关键配置:
properties复制# application.properties
spring.cloud.alibaba.seata.tx-service-group=my_order_tx_group
seata.service.vgroup-mapping.my_order_tx_group=default
特别注意:在菜品库存扣减时,采用先预扣减再实际扣减的两阶段方案,避免超卖。
4. 性能优化实战
4.1 MySQL优化方案
- 订单表按用户ID分片(user_id % 16)
- 建立复合索引:(user_id, create_time)用于用户订单查询
- 配置InnoDB缓冲池大小为物理内存的70%
4.2 Redis缓存策略
采用多级缓存架构:
- 本地缓存(Caffeine):缓存用户基本信息,TTL 5分钟
- Redis缓存:
- 菜品信息:TTL 1小时,采用主动更新策略
- 购物车数据:永不过期,但设置内存淘汰策略为allkeys-lru
5. 部署与监控
5.1 容器化部署
Docker Compose文件关键配置:
yaml复制services:
order-service:
image: order-service:1.0
deploy:
resources:
limits:
cpus: '2'
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
5.2 监控方案
- Prometheus采集SpringBoot Actuator指标
- Grafana配置业务看板,重点关注:
- 订单创建成功率
- 平均响应时间(P99<500ms)
- MySQL活跃连接数
6. 踩坑经验分享
- 跨域问题:开发环境经常出现的CORS问题,最终解决方案是在Gateway层统一处理:
java复制@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
- 日期序列化:前端显示时间戳问题,需要统一配置:
java复制@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
return builder -> {
builder.timeZone(TimeZone.getTimeZone("Asia/Shanghai"));
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
};
}
}
- 接口幂等性:订单创建接口必须做幂等控制,我们采用Redis分布式锁+唯一订单号方案:
java复制public String createOrder(OrderDTO orderDTO) {
String lockKey = "order:create:" + orderDTO.getUserId();
String orderNo = generateOrderNo();
try {
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, orderNo, 30, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("操作太频繁");
}
// 真正的创建订单逻辑...
} finally {
redisTemplate.delete(lockKey);
}
return orderNo;
}
这套系统经过3次大版本迭代,目前已在12家餐饮企业稳定运行,日均处理订单量超过5万。最大的收获是认识到:在餐饮系统开发中,数据一致性的优先级永远高于性能优化,任何可能引起订单金额计算错误的优化方案都应该被拒绝。
