1 Star 0 Fork 5.8K

朱鑫浩 / spring-boot-seckill

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
READMEmd.md 4.11 KB
一键复制 编辑 原始数据 按行查看 历史
朱鑫浩 提交于 2020-03-13 18:22 . init

启动后: Api测试地址 http://localhost:8080/seckill/swagger-ui.html

秒杀商品页地址: http://localhost:8080/seckill

作者说明: https://gitee.com/52itstyle/spring-boot-seckill/wikis/%E7%A7%92%E6%9D%80

SeckillController: 秒杀系统的七种实现: 秒杀一(最low实现): 删除success表,更新该商品为100(方便测试)。用CountDownLatch闭锁和线程池以作压测。查询seckill商品库存,大于0则扣库存并生成订单入库。 for循环中,创建runnable并执行流程,闭锁-1,放入线程池并发执行。闭锁await等待所有完成后,查询完成订单数。
两次:一次100个订单,一次102个订单。超卖现象:是因为在查询库存,扣减库存,生成订单的流程中。当并发查询库存时, 导致两次下单同时查询获取到的就是错误的库存数。

@Transactional: 为什么加了事务注解没有用?
这里加事务只是保证了查询库存和扣减库存 这个流程的原子性(如果查和改 这两个步骤哪个出现问题就回滚,以保证数据的正确性),但并不能保证同时只有一个线程查询库存。

@ServiceLimit:限流注解,限制同一个Ip频繁访问,因此导致超卖问题。

秒杀二(程序锁): 使用ReentrantLock,将查询库存,扣减库存和生成订单的流程加锁,一次只能一个线程访问。但是锁释放 和事务的提交的顺序还是会导致超卖的问题。
@Transactional声明式事务注解,其事务的流程,提交是放在哪里。和finally中的unlock锁释放的顺序,导致下单流程出问题。 应该在事务提交后再进行锁的释放,事务未提交就释放锁,就是事务未提交就有新的线程进来,新的事务读取前一个事务未提交的数据,导致脏读。 将@Transactional的事务级别设置为最高,将所放在controller层也可以。

秒杀三(AOP程序锁): 解决二中锁释放和事务提交顺序导致的问题,@Transactional以AOP注解的方式进行事务的拦截配置。那么锁此时也用AOP注解的方式,且order放在事务后面即可。

秒杀四(数据库悲观锁): 查询库存时for update锁表

秒杀五(数据库悲观锁): 数据库悲观锁 set num = num -1 and num>0 将查询和update放在同一条sql中。抢购多件的话 锁表比较慢。

秒杀六(数据库乐观锁): 加version字段,先查询库存,同时查询出version。更新库存时根据id和version查询,就不会出错了。 UPDATE seckill SET number=number-?,version=version+1 WHERE seckill_id=? AND version = ? 抢的人少时,会出现少买。

秒杀柒(进程内队列) : 用LinkedBlockingQueue,生成订单压入队列,另有一个类从队列消费,取出订单信息并入库。该类实现ApplicationRunner

秒杀八(Disruptor队列):

限流注解会导致少买

秒杀一(超卖) 最简单的查询更新操作,不涉及各种锁,会出现超卖情况。

秒杀二(超卖) 使用ReentrantLock重入锁,由于事物提交和锁释放的先后顺序也会导致超卖。

秒杀三(正常) 基于秒杀二场景的修复,锁上移,事物提交后再释放锁,不会超卖。

秒杀四(少买) 基于数据库悲观锁实现,查询加锁,然后更新,由于使用了 限流 注解(可自行注释),这里会出现少买。

秒杀五(正常) 基于数据库悲观锁实现,更新加锁并判断剩余数量。

秒杀六(正常) 基于数据库乐观锁实现,先查询商品版本号,然后根据版本号更新,判断更新数量。少量用户抢购的时候会出现 少买 的情况。

秒杀七(少买) 基于进程内队列 LinkedBlockingQueue 实现,同步消费,由于使用了 限流 注解(可自行注释),这里会出现少买。如果想正常,去掉startSeckil方法上的@ServiceLimit注解即可。

秒杀八(少买) 基于高性能队列 Disruptor实现,同步消费,由于使用了 限流 注解(可自行注释),这里会出现少买。如果想正常,去掉startSeckil方法上的@ServiceLimit注解即可。

SeckillDistributedController: 分布式秒杀:

Java
1
https://gitee.com/zxhhd/spring-boot-seckill.git
git@gitee.com:zxhhd/spring-boot-seckill.git
zxhhd
spring-boot-seckill
spring-boot-seckill
master

搜索帮助