优惠券秒杀(实现一人一单)

案例:(一人一单)

旧的:

这种优惠券优惠力度大应该一人只能消费一次。问题(我们一个人全抢了)

优化:(我们在库存充足的时候不是直接扣减库存的,而是判断一下这个订单是否存在了。不存在才扣减库存)

一人一单操作:

第一步:查询订单嘛(才能判断(将下面的查询用户id提上来先用))

第二步:判断是否存在了(不存在返回失败)

第三步:不存在还是之前的扣减库存

测试:(200并发应该只能卖一单)

出现了错误(这个1个用户还是下了多单)

问题分析:我们这里的逻辑与前面的库存思想是一样的,先查询再判断再扣减

按时我们的这里是多线程操作(也是出现了多线程穿插的情况)即为当我们第一个线程在判断出这个用户不存在0,但是还未扣减库存(用户信息添加进数据库(没有订单))的时候,其他线程也进来获取了也是0,他的判断还是没有。所以逻辑还是会让它扣减的。

解决(优化)思路:(还是加锁啊,这里就不能更新再来判断了,就必须是悲观锁了(syn))

第一步:我们这个整个逻辑(一人一单)进行封装:Ctrl+m。(就是将下面的变为一个函数,上面使用的时候直接调动)

封装好了(调用下面的封装函数)

第二步:加锁我们是先加在方法上的(syn),但是这样就锁住了整个方法,每个用户来都要获取锁,串行效率很慢)而且我们的事务范围是这个扣减库存的操作而不是整个类上面(前面是查询不需要加事务嘛)所以我们就将事务放到下面的这个锁的方法上了。

第三步:(优化:不要将整个方法锁住(提高效率),锁用户)

思路:我们缩小锁的范围,(我们只锁我们的用户id从而锁住我们的用户)一人一单中,我们只有在同一个用户来的时候我们才进行判断了(他的并发安全问题),其他用户我们就不加锁了。我们就使用关键字这种方法了(syn)锁住这个id再将下面的加在代码块中。

这里有个坑:

坑1:(我们这里是将id值一样的作为一把锁)但是我们每一次请求来这个id对象其实都是不同的,我们的对象变了,那么我们的锁也就变了(我们锁的操作是对象的,这是基本别忘了)。我们这里的tostring是不能保证其是根据值来加锁的。请看源码,其底层调用的是这个Long的一个静态函数,内部是一个new String()。New了一个字符串。所以我们再每一次调用这个toString的时候也是一个全新的字符串对象。所以这个锁对象又变了一次。(即使id是一样的(字符串),但是字符串对象还是不一样的)

优化1、(调用一个字符串方法,它的值相同返回的对象是一样的toString().intern())

确保当我们的用户的id一样的时候,锁是一样的。(锁的是当前用户)

坑2:(我们这里的锁范围又有点小了)我们的这个事务提交问题(我们是在方法内部加锁),我们这个事务是被spring管理的(@Transactiona)所以这个事务的提交是在我们函数执行完以后由spring才做的提交。

逻辑:我们先去开启事务,开始执行,然后获取锁,我们开始做下面的查询,查询我们再减库存,提交订单。这时我们是先释放锁再才会提交事务。那么在这个函数的最后的}结束后,这个锁就已经释放了(锁释放到spring提交事务中间还有点时间)。那么其他的线程就能够进来了。此时事其他线程进来查询订单(此时事务还没有提交,我们下面新增的订单还没有写入我们的数据库(和前面的数据库事务串起来。我们修改的时候只是改的表的数据,只有提交后数据库才会永久更改了))那么他也会进行扣减库存操作了(还是出现并发安全问题)

优化2、我们应该是在事务提交后才释放锁(我们将syn加在这个函数调用前面去加锁了)

坑3、上面优化后又出现事务问题了(我们是对下面的那个函数加了事务,没有给外面的这个函数(方法)加事务而外面这个函数再调用的时候是this.这样调用的 。其中他this拿到的是(目标对象不是代理对象)这个对象,而不是我们需要的他的代理对象。而我们需要知道我们的事务想要生效是我们的spring对这个类做了动态代理,拿到了这个类的代理对象。然后用这个下面函数做了事务处理)this拿到的是目标对象,而不是代理对象(代理对象才能做很多目标对象无法做的东西操作)没有事务操作功能的(这就是spring事务失效的几种可能性之一)。

优化3:我们去拿到我们事务的代理对象(AopContext.currentProxy()拿到代理对象也就是service接口嘛(别忘了我们代理这些都是实现了同一个接口))

最后我们还需要加一个依赖org.aspectj

再到这个启动类上去去加注解暴露这个代理对象true(暴露)

测试:

莫得问题了

45、优惠券秒杀(实现一人一单)相关推荐

  1. Redis解决秒杀中一人一单问题

    前言 在上一篇,通过实例演示了在高并发场景下多人抢购优惠券的超卖问题,并且利用redis+lua解决了超卖问题,但是一人只能抢一单的问题是否还在呢? 一人抢多单压测 可以发现,在经过改造时候,虽然解决 ...

  2. Redis 基础 - 优惠券秒杀《非集群》

    参考 Redis基础 - 基本类型及常用命令 Redis基础 - Java客户端 Redis 基础 - 短信验证码登录 Redis 基础 - 用Redis查询商户信息 摘要 用Redis生成保证唯一性 ...

  3. 【Redis】实战篇:优惠卷秒杀 (库存超卖问题、一人一单问题)

    文章目录 3.1 全局唯一ID 3.2 -Redis实现全局唯一Id 3.3 添加优惠卷 3.4 实现秒杀下单 3.5 库存超卖问题分析 3.6 乐观锁解决超卖问题 3.7 优惠券秒杀-一人一单 3. ...

  4. Redis实战11-实现优惠券秒杀下单

    本篇,咱们来实现优惠券秒杀下单功能.通过本篇学习,我们将会有如下收获: 1:优惠券领券业务逻辑: 2:分析在高并发情况下,出现超卖问题产生的原因: 3:解决超卖问题两种方案:版本号法及CAS法 4:乐 ...

  5. 实战篇--优惠券秒杀

    优惠券秒杀 全局唯一ID 当用户抢购时,就会生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增ID就存在一些问题: id的规律性太明显 受单表数据量限制 全局ID生成 ...

  6. Redis(4)优惠券秒杀

    优惠券秒杀 全局ID生成器 优惠券秒杀 秒杀实现 库存超卖 乐观锁实现 一人一单 分布式锁 分布式锁版本一 Redis分布式锁误删情况 解决分布式锁误删 分布式锁原子性问题 解决原子性问题 利用Jav ...

  7. 【Redis学习05】优惠券秒杀及其优化

    文章目录 1. 全局唯一ID 1.1 全局唯一ID介绍及生成策略 1.2 代码实现 1.3 总结 2. 优惠券秒杀下单 2.1 添加优惠券 2.2 优惠券秒杀功能 3. 超卖问题 3.1 问题分析 3 ...

  8. Redis(八) - Redis企业实战之优惠券秒杀

    文章目录 一.全局唯一ID 1. 全局ID生成器 2. 全局唯一ID生成策略 3. Redis自增ID策略 二.实现优惠券秒杀下单 1. 添加优惠券 2. 编写添加秒杀券的接口 三.实现秒杀下单 四. ...

  9. Redis 基础 - 优惠券秒杀《初步优化(异步秒杀)》

    Redis基础 - 基本类型及常用命令 Redis基础 - Java客户端 Redis 基础 - 短信验证码登录 Redis 基础 - 用Redis查询商户信息 Redis 基础 - 优惠券秒杀< ...

最新文章

  1. 热烈庆祝 ubuntu10.10发布
  2. ubuntu安装mysql远程_Ubuntu18.04下远程安装MySQL
  3. 文本”Hello, world.”显示的颜色是?
  4. vue 前期准备,项目结构
  5. volatile深入
  6. 计算机网络数据链路层次学习
  7. 【英语学习】【English L06】U07 Jobs L4 What do you think of our service?
  8. Look at Memory Cost via Batch Size
  9. 1200万!硅谷AI大牛一年赚够北京二环一套房
  10. Android ListView 滑动背景为黑色的解决办法 listview小知识整理
  11. tensorflow2.1学习--熟悉TensorFlow写整个项目即鸢尾花项目
  12. Linux虚拟机设置Samba服务
  13. 苹果电脑python编程里面怎么切到中文_苹果电脑输入法怎么切换到中文
  14. GoldenDict 上的那些精美版权词典(附下载地址)(英语、俄语、梵语、印地语)
  15. Spring Boot之自定义JSON转换器
  16. 扩展点系列之ApplicationContextAwareProcessor普通类获取Spring Bean - 第433篇
  17. 中小企业网站十大通病,你的站有没有?
  18. HTML元素分类:inline、inline-block、block
  19. 3U8633——雷达对民航的贡献
  20. 操作系统春招面试复习之:文件管理

热门文章

  1. 【NOIP普及组】 1945:【09NOIP普及组】多项式输出
  2. JUC-II CPU的微程序设计 计算机组成原理课程设计 微指令编码
  3. 非华为电脑多屏协同_苹果转华为后的真香体验1-非华为电脑体验跨屏协同,好用...
  4. 招聘运维开发leader
  5. 服务器:连接云服务器的端口是什么?
  6. 2.7 数值分析: 向量的范数
  7. 分布式学习(6)etcd@3@ API v3 gRPC_range,put,deleterange
  8. 全球十大外盘外汇交易平台排行榜
  9. Python练手项目:用中国地图验证四色地理
  10. 加密解密,MySQL单行函数,数学函数字符串日期时间,流程控制,完整详细可收藏查询SQL