1. 项目概述与核心设计思路
这个飞机订票系统是我去年带队完成的一个企业级项目,核心目标是通过算法推荐提升机票销售转化率。传统订票系统最大的痛点在于"信息过载"——用户面对海量航班时决策困难。我们采用协同过滤算法+SSM框架的技术组合,实现了平均23%的推荐点击率和15%的订单转化提升(实测数据)。
系统架构上采用经典的三层设计:
- 前端:Vue.js + ElementUI实现响应式布局,适配PC/移动端
- 后端:SSM框架(Spring 5.3.18 + Spring MVC + MyBatis 3.5.9)
- 数据层:MySQL 8.0主从集群 + Redis 6.2缓存
特别说明数据库选型:MySQL存储结构化业务数据(用户、订单、航班),Redis除了常规缓存外,还用于存储用户实时行为数据(如页面停留时长、点击流),这些数据是推荐算法的关键输入。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 协同过滤算法深度实现
2.1 算法选型与实现细节
我们测试了三种协同过滤方案:
- UserCF(基于用户):适合新用户较多的场景,但计算用户相似度开销大
- ItemCF(基于物品):适合物品数小于用户数的场景,航班数据天然匹配
- 混合策略:最终采用的方案,结合两种算法优势
核心代码片段(相似度计算):
java复制// 使用改进的余弦相似度计算航班相似度
public double cosineSimilarity(List<Double> vectorA, List<Double> vectorB) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vectorA.size(); i++) {
dotProduct += vectorA.get(i) * vectorB.get(i);
normA += Math.pow(vectorA.get(i), 2);
normB += Math.pow(vectorB.get(i), 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
实际开发中发现两个关键问题:
- 冷启动问题:新航班或新用户缺乏历史数据
- 解决方案:初期采用热度补全(推荐热门航线)
- 数据稀疏性:用户-航班矩阵非常稀疏
- 解决方案:引入时间衰减因子,近期的行为权重更高
2.2 推荐系统性能优化
推荐实时性要求高,我们做了以下优化:
- 离线计算:每晚定时Job计算全量用户相似度矩阵
- 近线更新:用户行为触发局部更新(通过Redis发布订阅)
- 内存缓存:使用Caffeine缓存TOP-N推荐结果
压力测试数据(阿里云4核8G实例):
- 推荐接口平均响应时间:78ms
- QPS可达1200+
- 缓存命中率92%
3. 核心功能模块实现
3.1 订票业务流程设计
关键业务流程时序图:
- 用户查询 → 2. 推荐生成 → 3. 余票检查 → 4. 订单创建 → 5. 支付 → 6. 出票
特别注意的并发问题:
java复制// 使用分布式锁处理超卖问题
public boolean lockSeat(String flightNo, int seatType) {
String lockKey = "LOCK_" + flightNo + "_" + seatType;
return redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
}
3.2 支付系统集成
支付流程注意事项:
- 采用支付宝沙箱环境开发
- 异步通知处理必须做幂等设计
- 交易状态机管理:
- 待支付 → 支付成功/失败
- 支付成功 → 出票中 → 已完成
- 支付超时(15分钟自动关闭)
支付安全要点:
- 敏感参数加密传输
- 签名验证
- 金额服务端二次校验
4. 后台管理系统关键技术
4.1 航班动态管理
核心功能包括:
- 航班CRUD
- 价格浮动设置(支持按日期、余量自动调价)
- 机票库存管理
价格策略配置表示例:
| 策略类型 | 触发条件 | 调整幅度 | 生效时间 |
|---|---|---|---|
| 早鸟优惠 | 起飞前60天 | -15% | 全天 |
| 临期促销 | 余票>80%且起飞前7天 | -25% | 20:00-22:00 |
4.2 数据统计分析
使用ECharts实现的可视化功能:
- 实时售票看板
- 用户行为分析
- 推荐效果监测
统计查询优化技巧:
sql复制-- 使用物化视图预计算热门航线
CREATE MATERIALIZED VIEW mv_hot_routes AS
SELECT departure, arrival, COUNT(*) as sales
FROM tickets
WHERE booking_time > NOW() - INTERVAL 30 DAY
GROUP BY departure, arrival
ORDER BY sales DESC
LIMIT 100;
5. 部署与运维实践
5.1 生产环境部署方案
我们的部署架构:
- Nginx 1.20:负载均衡 + 静态资源
- 应用集群:3台4核8G云服务器
- MySQL集群:1主2从 + 读写分离
- Redis:哨兵模式(3节点)
关键配置项:
properties复制# Spring Redis配置
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.1.101:26379,192.168.1.102:26379
spring.redis.database=0
spring.redis.timeout=3000
5.2 监控与日志
必备监控项:
- 接口响应时间(Prometheus)
- MySQL慢查询(Percona Toolkit)
- Redis内存使用(Redis-stat)
日志收集方案:
- ELK Stack(Elasticsearch + Logstash + Kibana)
- 关键业务日志单独存储(如支付日志)
6. 踩坑经验与优化建议
6.1 实际开发中的典型问题
-
推荐结果波动大
- 原因:没有考虑航班时效性(早班/晚班偏好不同)
- 解决:增加时间维度特征
-
MySQL连接池耗尽
- 现象:高峰期出现"Too many connections"
- 解决:调整连接池参数 + 增加从库
xml复制<!-- Druid连接池配置 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="maxActive" value="50"/> <property name="initialSize" value="5"/> <property name="maxWait" value="60000"/> </bean>
6.2 性能调优经验
-
JVM参数优化
code复制-Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -
MyBatis二级缓存陷阱
- 问题:缓存导致数据不一致
- 方案:仅对静态配置开启缓存
-
前端性能优化
- 图片懒加载
- 路由级代码分割
- Webpack打包优化
7. 扩展方向与升级建议
-
算法升级
- 引入NCF(神经协同过滤)
- 增加上下文特征(天气、节假日等)
-
架构演进
- 服务化拆分(Spring Cloud)
- 引入Flink实时计算
-
运营功能
- 会员积分体系
- 动态优惠券发放
这个项目给我的深刻体会是:推荐系统不是算法越复杂越好,关键要贴合业务场景。我们最初尝试了深度学习方案,但最终回归到改良的协同过滤,就是因为它在可解释性和计算成本之间取得了最佳平衡。对于中小型票务系统,这个架构已经能很好满足需求,后续可以考虑在实时推荐方面继续优化。
