秒杀场景下不同高并发方案性能压测对比与实战分析

37 阅读6分钟

大家好,相信很多致力于Java后端开发的同学,对"苍穹外卖"、"黑马点评"、"云商城"这类经典项目都不会陌生。我也曾跟随黑马程序员及其他技术文档,完整实现过这些项目。在它们的亮点中,高并发处理方案无疑是重中之重。然而,这些方案之间的实际性能差异究竟有多大?为了解开心中的疑惑,也为了丰富个人简历中的实践内容,我设计并实施了一次针对"秒杀"场景的高并发压力测试。本篇文档将详细记录我的实验设计、实现与结果分析。

 1. 业务背景与实验设计

  1.1 核心业务流程

  一个典型的秒杀下单流程可抽象为以下步骤:

 1. 请求拦截:校验是否为重复请求(如短时间内的频繁点击)。

 2. 资格校验:校验用户是否已购买过(一人一单)。

 3. 库存校验:校验商品库存是否充足。

 4. 订单创建:扣减库存,在数据库中创建订单记录。

 

1.2 实验方案对比

  为探究不同技术栈的性能表现,我设立了以下两个实验组:

 对照组(数据库直连组):

 核心思想:将并发控制的重担完全交给数据库和应用层代码。

 技术实现:

  库存防超卖:通过MySQL的"SELECT ... FOR UPDATE"(悲观锁)实现。

  一人一单 & 防重:由Java应用层代码在数据库事务中校验保证。

 

实验组(优化组):

 核心思想:利用Redis的高性能与原子性操作,以及消息队列的异步削峰能力,将压力从数据库剥离。

 技术实现:

 防重请求:通过Redisson分布式锁实现。

 一人一单 & 库存防超卖:通过Redis + Lua脚本的原子性操作确保。

 数据持久化:通过RocketMQ普通消息异步写入数据库,实现最终一致性。

 

1.3 实验环境

  硬件:单机测试(笔记本:ThinkPad Neo 14)。

  压测工具:K6(注:初期曾使用Apifox,但其在极限压测场景下数据不够精确,故更换为专业工具K6。Apifox更适合日常接口调试与流程测试)。

  数据库连接池:50

  初始库存:1000

 

  1. 压测结果与数据分析

  以下是两组方案在不同并发用户数下的关键性能指标对比。

  2.1 对照组(数据库直连组)性能数据

  并发50用户:

 P95响应时间:204.01ms

 平均响应时间:129.74ms

 QPS:381.47/s

 总请求数:3,876

 成功率(got ticket):25%(1000/3876)

 HTTP失败率:0.00%

 

并发100用户:

 P95响应时间:399.5ms

 平均响应时间:309.77ms

 QPS:317.74/s

 总请求数:3,261

 成功率(got ticket):30%(1000/3261)

 HTTP失败率:0.00%

 

关键观察:

 无HTTP错误:所有请求都正常返回,接口可用性100%。

 响应延迟显著:并发100时P95接近400ms,用户体验开始劣化。

 QPS不升反降:并发翻倍但QPS下降17%,说明数据库已成为瓶颈。

 悲观锁阻塞:大量线程等待数据库锁,CPU利用率低但连接池耗尽。

 

2.2 实验组(Redis+MQ优化组)性能数据

  并发50用户:

 P95响应时间:28.47ms

 平均响应时间:8.96ms

 QPS:5519.13/s

 总请求数:55,226

 成功率(got ticket):1%(1000/55226)

 HTTP失败率:0.00%

 

并发100用户:

 P95响应时间:74.43ms

 平均响应时间:22.94ms

 QPS:4333.56/s

 总请求数:43,397

 成功率(got ticket):2%(1000/43397)

 HTTP失败率:0.00%

 

关键观察:

 性能飞跃:QPS提升14.5倍(并发50)和13.6倍(并发100)。

 延迟极低:P95控制在30-75ms,用户体验流畅。

 承载能力:总请求量是对照组的14倍,系统吞吐量大幅提升。

 精准控流:成功率仅1-2%,说明Redis原子性过滤有效,仅真实扣减库存的请求进入下游。

 

2.3 性能对比总结

 

指标数据库直连组(并发100)Redis优化组(并发100)提升幅度
吞吐量(QPS)317.74/s4333.56/s13.6倍
响应延迟(P95)399.5ms74.43ms降低81%
总处理能力3,261请求43,397请求13.3倍
平均响应时间309.77ms22.94ms 降低93%
  1. 核心结论与方案对比

 

3.1 数据解读与业务意义

为什么Redis组成功率只有1-2%?

这是预期内的优秀表现,说明:Redis原子性扣减成功拦截了99%的无效请求(库存不足/重复购买)。 只有真正抢到库存的1000个请求被放行,其余直接返回"已售罄"。 对照组25-30%的"成功率"实际上是数据库层面的竞争失败重试,并非真正成功。

 为什么Redis组并发100时QPS比并发50低?

并发50时:系统未达到瓶颈,单机Redis性能充分发挥(5500+ QPS)。

并发100时:可能受限于单机网络带宽或应用层线程数,但4333 QPS仍是对照组的13.6倍。

延迟对比的业务价值:

数据库组点击秒杀按钮需等待0.4秒,Redis组仅需0.03秒,几乎无感知。

3.2 技术方案深度对比

数据库直连组(悲观锁方案):

优点:实现简单,数据强一致性,无需引入额外组件。

缺点:数据库成为瓶颈,连接数受限,锁竞争激烈,性能随并发线性下降。

Redis优化组(缓存+异步方案):

优点:Redis单线程+Lua脚本保证原子性,无锁竞争。 内存操作性能比磁盘高2-3个数量级。 MQ异步解耦,削峰填谷,保护数据库。

缺点: 系统复杂度增加,需维护Redis和MQ。 最终一致性需处理消息丢失、重复消费。 需要额外的库存回滚和补偿机制。

 

  1. 实战踩坑与优化建议

 4.1 压测过程中的关键发现

 数据库连接池耗尽(对照组):

 现象:并发100时QPS反而下降,连接等待时间增加。

 根因:SELECT ... FOR UPDATE持有锁时间过长,连接无法释放。

 建议:数据库方案必须配合连接池监控和熔断降级。

 

Redis单节点性能天花板(实验组并发100):

 现象:QPS从5500降至4300,未达到线性扩展。

 根因:单机Redis网络IO或CPU单线程瓶颈。

 

库存精准扣减验证:

 验证方式:检查数据库最终库存是否为0,订单数是否为1000。

 结果:两组方案均无超卖,但Redis组无重复订单,对照组需去重。

 

  1. 写在最后

  本次压测用真实数据验证了"缓存+异步"架构在高并发秒杀场景下的绝对优势: 14倍吞吐量提升、81%延迟降低、零超卖风险 —— 这就是Redis+MQ方案交出的答卷。 但也要清醒认识到: 对照组并非一无是处:它的强一致性和简单性,在低并发场景(<50 QPS)下完全够用。 优化组也有代价:引入了Redis、MQ运维复杂度,以及最终一致性的业务适配成本。