1. 系统需求分析与场景设计
火车票务系统最核心的挑战在于如何应对节假日期间瞬时爆发的购票请求。我曾在某次春运期间实测12306系统的并发量,峰值时每秒要处理超过50万次查询请求。对于课程设计项目,我们需要聚焦三个核心场景:
1.1 用户角色建模
- 旅客端需求:余票查询(90%的流量集中于此)、购票(涉及库存扣减)、改签/退票(事务性操作)
- 管理员端需求:车次管理(增删改查)、票价调整(动态定价)、数据统计(可视化报表)
1.2 高并发典型场景
- 秒杀场景:当热门车次放票时,1000人同时抢最后50张票
- 库存同步:某旅客退票后,如何实时更新余票显示
- 排队机制:当系统过载时,如何优雅降级而非直接崩溃
1.3 非功能性需求
- 响应时间:查询接口<500ms,下单接口<1s
- 可靠性:99.9%可用性(年故障时间<8.7小时)
- 数据一致性:避免超卖(卖出的票数>实际座位数)
提示:使用Redis的INCR命令实现原子性库存扣减,比传统数据库SELECT+UPDATE方案性能提升100倍
2. 技术架构设计
2.1 分层架构
graph TD A[客户端] --> B[Nginx负载均衡] B --> C[API网关] C --> D[微服务集群] D --> E[Redis缓存] D --> F[MySQL集群]2.2 微服务拆分
- 用户服务:处理认证、权限
- 车次服务:管理时刻表、站点
- 订单服务:处理购票/退票业务流
- 支付服务:对接第三方支付
- 通知服务:短信/邮件提醒
2.3 关键技术选型对比
| 技术点 | 传统方案 | 高并发方案 | 优势对比 |
|---|---|---|---|
| 数据库 | 单机MySQL | MySQL分库分表 | 吞吐量提升10倍 |
| 缓存 | 无 | Redis集群 | 查询性能提升1000倍 |
| 消息队列 | 同步调用 | RabbitMQ异步解耦 | 抗流量冲击能力提升 |
| 分布式事务 | 本地事务 | Seata+SAGA模式 | 故障恢复率从90%→99.99% |
3. 核心模块实现
3.1 购票流程设计
// 伪代码示例:购票核心逻辑 public Result purchaseTicket(Long userId, Long trainId) { // 1. 分布式锁防重提交 String lockKey = "lock:purchase:" + userId; if (!redisLock.tryLock(lockKey, 10, TimeUnit.SECONDS)) { return Result.fail("操作过于频繁"); } try { // 2. 校验库存(Redis原子操作) String stockKey = "stock:" + trainId; Long remain = redisTemplate.opsForValue().decrement(stockKey); if (remain < 0) { redisTemplate.opsForValue().increment(stockKey); // 回滚 return Result.fail("已售罄"); } // 3. 创建订单(数据库事务) return transactionTemplate.execute(status -> { Order order = orderService.createOrder(userId, trainId); paymentService.processPayment(order); return Result.success(order); }); } finally { redisLock.unlock(lockKey); } }3.2 库存同步方案
- 初始加载:系统启动时将MySQL库存同步到Redis
- 实时更新:
- 购票成功:Redis.decr + MySQL异步扣减
- 退票操作:Redis.incr + MySQL异步增加
- 定时校对:每小时全量核对Redis与MySQL数据
3.3 防黄牛策略
- 人机验证:滑动拼图+点击验证
- 行为分析:同一IP/设备频繁操作触发限流
- 业务规则:单个账号限购5张/车次
4. 性能优化实战
4.1 缓存设计技巧
- 多级缓存:本地缓存(Caffeine) + Redis集群
- 缓存预热:提前加载热门车次数据
- 缓存穿透:对空值设置短时间TTL
4.2 数据库优化
-- 建立复合索引提升查询效率 CREATE INDEX idx_train_date ON tickets(train_number, departure_date); -- 分库分表策略(按车次ID哈希分片) sharding-key: train_id % 164.3 压力测试数据使用JMeter模拟1万并发用户:
| 优化前 | 优化后 | QPS提升 |
|---|---|---|
| 200请求/秒 | 3500请求/秒 | 17.5倍 |
| 平均响应2.3s | 平均响应280ms | 88%降低 |
5. 课程设计交付要点
5.1 UML建模关键图
- 用例图:区分旅客/管理员操作边界
- 状态图:订单状态流转(待支付/已出票/已退票)
- 时序图:购票过程中的服务交互
5.2 原型设计建议
- 高保真原型工具:Axure/Figma
- 必含界面:
- 车次查询页(带筛选条件)
- 订单确认页(座位可视化选择)
- 个人中心(订单列表)
5.3 答辩常见问题
- 如何保证Redis与MySQL数据一致?
- 系统最大能支撑多少并发?
- 如果Redis宕机怎么处理?
我在实际项目中遇到过缓存雪崩问题,解决方案是给不同的key设置随机过期时间。建议同学们在演示时准备应急预案,比如手动切换读数据库的降级方案。