1. 项目背景与核心需求
地铁售票系统作为城市轨道交通运营的核心业务支撑平台,其技术实现直接关系到千万级用户的出行体验。这个基于Java技术栈的毕业设计项目,本质上是要构建一个具备完整票务管理功能的分布式系统。从技术视角来看,这类系统需要同时满足三个维度的要求:
- 高并发处理:早晚高峰时段需支撑每分钟上万次的票务请求
- 事务一致性:确保售票、退票、改签等资金操作绝对准确
- 系统可扩展:能够灵活应对新线路开通、票价策略调整等业务变化
我在实际参与某二线城市地铁AFC系统升级时,就遇到过传统单体架构在客流激增时出现数据库连接池耗尽的问题。这促使我们在新系统中采用Spring Cloud微服务架构,将票务核心模块与清分结算模块解耦。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计解析
2.1 整体架构方案
采用经典的三层架构模式,但在数据访问层做了特殊优化:
code复制表现层(Web)
↓
业务逻辑层(Service)
↓
数据访问层(DAO)
特别在DAO层实现了双缓存策略:
- 本地Caffeine缓存处理热点车票查询
- Redis集群缓存余票实时数据
- 通过Redisson实现分布式锁保证库存扣减一致性
2.2 技术选型对比
| 技术组件 | 选型理由 | 替代方案 |
|---|---|---|
| Spring Boot 2.7 | 内嵌Tomcat简化部署,starter机制快速集成其他组件 | Quarkus |
| MyBatis-Plus | 提供Lambda表达式查询,自动分页插件大幅减少样板代码 | JPA/Hibernate |
| ShardingSphere | 按线路分库分表,解决单表数据量过大问题 | MyCat |
| RocketMQ | 削峰填谷处理订票消息,确保高峰时段系统稳定 | Kafka |
实际开发中发现MyBatis-Plus的乐观锁插件在秒杀场景下会产生大量失败请求,后来改用Redisson的看门狗机制实现分布式锁
3. 核心业务模块实现
3.1 票务状态机设计
票务生命周期管理采用状态机模式,通过Spring StateMachine实现:
java复制public enum TicketState {
INITIALIZED,
RESERVED,
PAID,
CONSUMED,
REFUNDING,
REFUNDED
}
@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter {
@Override
public void configure(StateMachineTransitionConfigurer transitions) {
transitions
.withExternal()
.source(TicketState.INITIALIZED)
.target(TicketState.RESERVED)
.event(TicketEvent.RESERVE);
}
}
3.2 分布式事务方案
采用Seata的AT模式解决跨服务事务问题:
- 购票服务扣减库存
- 支付服务处理扣款
- 票务服务生成电子票
关键配置:
properties复制# seata配置
seata.tx-service-group=metro_ticket_group
seata.service.vgroup-mapping.metro_ticket_group=default
4. 性能优化实战
4.1 余票查询优化
通过布隆过滤器预判车次是否存在余票:
java复制public class TicketBloomFilter {
private static final BloomFilter<String> bloomFilter =
BloomFilter.create(Funnels.stringFunnel(), 1000000, 0.01);
public static boolean mightContain(String trainCode) {
return bloomFilter.mightContain(trainCode);
}
}
4.2 数据库分库策略
按线路ID进行分片,配置示例:
yaml复制spring:
shardingsphere:
datasource:
names: ds0,ds1
sharding:
tables:
ticket_order:
actual-data-nodes: ds$->{0..1}.ticket_order_$->{0..15}
database-strategy:
inline:
sharding-column: line_id
algorithm-expression: ds$->{line_id % 2}
5. 安全防护措施
5.1 防黄牛机制
- 行为验证码:采用滑动拼图验证
- 购买频率限制:Redis实现滑动窗口计数
java复制public boolean checkFrequency(String userId) { String key = "limit:" + userId; long count = redisTemplate.opsForZSet().count(key, System.currentTimeMillis() - 3600000, System.currentTimeMillis()); return count < 10; }
5.2 敏感数据加密
采用国密SM4算法加密身份证号:
java复制public class SM4Util {
private static final String ALGORITHM_NAME = "SM4";
public static String encrypt(String plainText) {
// 实现细节省略
}
}
6. 监控与运维
6.1 全链路监控
集成SkyWalking实现调用链追踪:
yaml复制spring:
cloud:
sleuth:
sampler:
probability: 1.0
skywalking:
enabled: true
service-name: ticket-service
6.2 日志收集方案
采用ELK栈处理日志:
- Logstash配置Grok解析日志格式
- Elasticsearch建立时间序列索引
- Kibana制作实时监控看板
7. 测试策略
7.1 压力测试指标
使用JMeter模拟10万并发:
- 平均响应时间 < 500ms
- 错误率 < 0.1%
- 吞吐量 > 8000TPS
7.2 混沌工程实践
通过ChaosBlade注入以下故障:
- 随机杀死票务服务实例
- 模拟网络延迟500ms
- 填充Redis内存触发LRU
8. 部署架构
采用Kubernetes实现高可用部署:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: ticket-service
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
9. 典型问题排查
9.1 缓存击穿问题
现象:某热门车次查询导致数据库负载飙升
解决方案:
- 使用互斥锁重建缓存
- 设置逻辑过期时间
- 缓存预热策略
9.2 分布式锁失效
场景:跨机房部署时出现锁失效
优化方案:
- 改用Redisson红锁算法
- 设置看门狗续期时间30秒
- 增加锁持有日志
10. 扩展方向建议
- 生物识别支付:集成虹膜/指纹支付
- 智能票务预测:LSTM预测购票高峰
- 无感支付方案:结合车载RFID技术
在真实项目交付过程中,我们发现当余票库存低于5%时,系统需要动态切换查询策略——从Redis缓存直接查库,虽然会增加约200ms延迟,但能避免缓存与数据库不一致导致的超卖问题。这个经验来自某次线上事故后的复盘,常规文档中很少会提及这类细节。
