商品秒杀项目

商品秒杀项目(思路版)

需要的数据库表

  • 商品表
  • 订单表
  • 秒杀商品表
  • 秒杀订单表 包括秒杀商品id和用户id

简单流程

  • 点击秒杀
  • 是否登录
  • 查询库存(库存=0,商品被抢空)
  • 查询重复购买(每人只允许在秒杀订单表中只有一条数据)
  • 可以秒杀
    • 秒杀商品库存-1
    • 生成订单
    • 生成秒杀订单
  • 至此秒杀成功

库存超卖

JMeter

一款测压工具

测试发现,1000个线程即1000个用户同时秒杀,会产生大量的订单

流程分析

  • 在高并发下,很多请求同时查询到商品库存信息
  • 当两个用户并发SELECT库存后,两个用户获取到的库存是相等的,再UPDATE设置库存-1,相当于只减少了一件
  • 因为查询库存和库存-1的操作不是一个原子操作
  • 所以解决方案主要就是对查库存修改库存两步操作的原子化

超卖解决方案

悲观锁(syncronized)

在秒杀service方法上添加syncronized来上锁,来保证秒杀服务是串行执行的(有问题,看注意)。需要把syncronized加在controller层,这样就比事务的范围大了

注意:如果事务注解@Transactional添加状态下,对方法进行加锁,仍然会出现错误,因为当一个加锁方法执行完成后,由于事务的存在,当前线程的服务并没有被提交,这时新的线程到来,拿到的仍然是旧的库存,从而产生超卖

问题:悲观锁同一时间只允许一个线程运行,对用户体验很差

乐观锁

利用数据库定义的version字段,表示当前修改的版本,很多JUC的API都使用了类似的思想,添加stamp表示版本信息(此内容查看我的JUC专题)

获取库存的同时获取当前版本号,修改库存时修改version=version+1并且WHERE 中添加 version = #{versionId} ,如果在两步操作之间其他用户修改了库存也会修改version,就会让本线程修改失败(因为根据WHERE version = #{versionId} 已经查不到该条数据了,就会返回0),这样多线程并发情况下,只有一个线程能完成对库存的修改

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踢足球的程序员·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值