1. 项目背景与核心挑战
去年帮学弟调试他的毕业设计时,第一次见识到演唱会抢票系统的真实压力场景。当模拟5000并发用户抢购周杰伦演唱会门票时,他那套单体架构的系统在3秒内直接崩溃——这正是分布式系统存在的意义。
这个基于SpringCloud的分布式抢票系统,本质上要解决三个核心问题:
- 高并发下的库存超卖(两个用户同时买到同一个座位)
- 分布式环境下的数据一致性(不同节点看到的余票数不同)
- 突发流量下的系统雪崩(一个服务崩溃引发连锁反应)
提示:真正的抢票场景远比课堂Demo复杂。某票务平台的技术分享显示,顶流演唱会开售时QPS峰值可达50万+,相当于每秒要处理整个鸟巢观众席的座位请求。
2. 技术栈选型与架构设计
2.1 SpringCloud组件矩阵
这套系统采用了经典的SpringCloud Alibaba套件:
- Nacos:比Eureka更适合国内环境的服务注册中心,实测注册发现延迟<50ms
- Sentinel:配置「慢调用比例」熔断策略,当API响应时间>500ms时自动降级
- OpenFeign:声明式服务调用,配合自定义重试策略解决网络抖动问题
- Gateway:全局鉴权过滤+路由转发,我们在这里实现了恶意IP封禁功能
java复制// 典型熔断配置示例
@SentinelResource(
value = "ticketService",
fallback = "localCacheFallback",
blockHandler = "rushLimitHandler"
)
public TicketInfo getTicket(Long eventId) {
// 核心抢票逻辑
}
2.2 分布式事务方案对比
针对"扣库存→创建订单→支付"这个典型分布式事务场景,我们测试了四种方案:
| 方案 | TPS | 数据一致性 | 实现复杂度 | 选型结果 |
|---|---|---|---|---|
| Seata AT模式 | 1200 | 强一致 | ★★★★ | 最终备用 |
| TCC(Try-Confirm-Cancel) | 2800 | 最终一致 | ★★★ | 核心采用 |
| 本地消息表 | 3500 | 最终一致 | ★★ | 辅助场景 |
| Redis分布式锁 | 1800 | 弱一致 | ★ | 弃用 |
最终选择TCC方案,因为:
- 抢票业务能天然拆分为try(预占库存)、confirm(确认订单)、cancel(释放库存)三阶段
- 配合Hystrix舱壁模式,将不同演唱会的抢票请求隔离到独立线程池
3. 核心业务逻辑实现
3.1 库存扣减的防超卖设计
单纯的UPDATE stock SET count=count-1 WHERE id=? AND count>0在分布式环境下仍会出现超卖。我们的解决方案:
- 双重校验锁:先用Redis分布式锁(Redisson实现)拦截大部分并发
java复制RLock lock = redissonClient.getLock("ticket_" + ticketId);
try {
if (lock.tryLock(100, 10, TimeUnit.MILLISECONDS)) {
// 进入数据库操作
}
} finally {
lock.unlock();
}
- 版本号乐观锁:数据库增加version字段,更新时带版本校验
sql复制UPDATE ticket_stock
SET count=count-1, version=version+1
WHERE id=? AND version=? AND count>0
- 库存预扣机制:用户抢到资格后先占位15分钟,未支付则释放
3.2 热点数据优化方案
当某场演唱会特别火爆时,会出现「热点Key」问题。我们通过:
- 本地缓存:使用Caffeine缓存静态场次信息,命中率>95%
- 库存分段:将10000张票拆分为20个库存段,通过用户ID哈希分散压力
- 读写分离:查询走从库,通过ShardingSphere实现自动路由
4. 系统压测与调优记录
使用JMeter进行阶梯式压测时,发现了几个关键性能瓶颈:
-
MySQL连接池耗尽:
- 现象:200并发时出现"Timeout waiting for connection"
- 解决:调整Druid参数,将initialSize从5改为50,加上testWhileIdle配置
-
Redis大Key阻塞:
- 现象:存储用户抢票记录的Hash结构达到1MB
- 解决:拆分为多个小Hash,通过
userID%16分散到不同slot
-
Full GC频繁:
- 现象:Young GC 2秒/次,Full GC 10秒/次
- 解决:JVM参数调整为-Xmx2048m -Xms2048m -XX:MaxGCPauseMillis=200
优化前后关键指标对比:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 平均响应时间 | 1200ms | 280ms |
| 最大QPS | 3200 | 8500 |
| 错误率 | 8.7% | 0.2% |
5. 毕业设计中的加分项实践
要让这个项目在答辩中脱颖而出,建议补充这些亮点:
-
可视化监控:
- 通过Prometheus+Grafana监控黄金指标(QPS/RT/错误率)
- 特别展示熔断器触发时的流量断崖效果
-
混沌工程测试:
- 使用ChaosBlade模拟网络延迟、节点宕机
- 记录系统自恢复过程,体现高可用设计
-
动态限流演示:
- 在Gateway层实现基于用户等级的差异化限流
- 比如普通用户100QPS,VIP用户500QPS
这个项目最让我意外的收获是:分布式环境下的时间同步问题。当NTP服务出现波动时,居然导致不同节点生成的订单时间戳乱序,进而影响后续的统计分析。最后通过接入阿里云的NTP服务才彻底解决——这种实战中的细节,才是毕业设计真正该呈现的精华。
