在秒杀系统设计中,超卖是一个经典、常见的问题,任何商品都会有数量上限,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的难点。

一、问题描述

在多个用户同时发起对同一个商品的下单请求时,先查询商品库存,再修改商品库存,会出现资源竞争问题,导致库存的最终结果出现异常。问题:
当商品A一共有库存15件,用户甲先下单10件,用户乙下单8件,这时候库存只能满足一个人下单成功,如果两个人同时提交,就出现了超卖的问题。

二、解决的三种方案

1.解决方案1

  • 悲观锁
    当查询某条记录时,即让数据库为该记录加锁,锁住记录后别人无法操作,使用类似如下语法:
select stock from tb_sku where id=1 for update;SKU.objects.select_for_update().get(id=1)在这里插入代码片
  • 悲观锁类似于我们在多线程资源竞争时添加的互斥锁,容易出现死锁现象,采用不多。

2.解决方案2

  • 乐观锁
    乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新。类似如下操作:
update tb_sku set stock=2 where id=1 and stock=7;SKU.objects.filter(id=1, stock=7).update(stock=2)
  • 使用乐观锁需修改数据库的事务隔离级别:
    使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交(Read committed)。
    修改方式:

3.解决方案3

  • 任务队列
    将下单的逻辑放到任务队列中(如celery),将并行转为串行,所有人排队下单。比如开启只有一个进程的Celery,一个订单一个订单的处理。

三、网上超卖问题解决方案节选

节选自如何解决秒杀系统的性能问题和超卖的讨论的片段:如何解决秒杀系统的性能问题和超卖的讨论

解决方案2:
  引入队列,然后将所有写DB操作在单队列中排队,完全串行处理。当达到库存阀值的时候就不在消费队列,并关闭购买功能。这就解决了超卖问题。
  优点:解决超卖问题,略微提升性能。
  缺点:性能受限于队列处理机处理性能和DB的写入性能中最短的那个,另外多商品同时抢购的时候需要准备多条队列。

解决方案3:
  将写操作前移到Memcached中,同时利用Memcached的轻量级的锁机制CAS来实现减库存操作。
  优点:读写在内存中,操作性能快,引入轻量级锁之后可以保证同一时刻只有一个写入成功,解决减库存问题。
  缺点:没有实测,基于CAS的特性不知道高并发下是否会出现大量更新失败?不过加锁之后肯定对并发性能会有影响。

解决方案4:
  将提交操作变成两段式,先申请后确认。然后利用Redis的原子自增操作(相比较MySQL的自增来说没有空洞),同时利用Redis的事务特性来发号,保证拿到小于等于库存阀值的号的人都可以成功提交订单。然后数据异步更新到DB中。
  优点:解决超卖问题,库存读写都在内存中,故同时解决性能问题。
  缺点:由于异步写入DB,可能存在数据不一致。另可能存在少买,也就是如果拿到号的人不真正下订单,可能库存减为0,但是订单数并没有达到库存阀值。

解决秒杀系统超卖问题的三种方案相关推荐

  1. Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:涛哥谈篮球 来源:toutiao.com/i68366119 ...

  2. redis如何解决秒杀超卖java_Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了...

    作者:涛哥谈篮球 来源:toutiao.com/i6836611989607809548 问题描述 在众多抢购活动中,在有限的商品数量的限制下如何保证抢购到商品的用户数不能大于商品数量,也就是不能出现 ...

  3. Redis解决商品秒杀与超卖

    这个是实体店我们会看到的场景,100件商品,1人1件,最后200人中只有100人能买到商品,剩下100人只能空手而归.如果您开了家网店,同样你开起了秒杀的活动,可能同时会有1000人通过不同的终端访问 ...

  4. java的“看门狗”锁续期可以用php redis这样实现【php锁续期、分布式锁、无锁请求队列超卖】解决【商家超卖(商品库存控制)、用户超买(秒杀订单控制)】问题。非demo 线上一直在用

    要求与痛点描述 1.不允许使用库存创建队列 因为库存如果是10w难道要创建一个10w长度的队列吗 2.不允许对整个业务过程加锁 可能业务执行时间很长 导致锁粒度太大 影响并发量 3.如果业务时间大于锁 ...

  5. 抢购 mysql 优化_处理抢购、秒杀应用场景降低“超卖”发生几个优化方案(php)...

    加深下文件锁理论 flock-轻便的咨询文件锁定 说明 参数 handle 文件系统指针,是典型地由fopen()创建的resource(资源). operation operation可以是以下值之 ...

  6. php 有关秒杀防止超卖面试题

    秒杀,怎么防止库存超卖 所谓秒杀,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式.由于商品价格低廉,往往一上架就被抢购一空,有时只用一秒钟. 先来就库存超卖的问题作描述: ...

  7. win7系统wifi没有网络连接到服务器,Win7无线Wifi无法连接怎么办?win7系统Wifi无法连接的三种故障原因及解决方法...

    当我们准备接入一个Wifi的时候,发现怎么样都连不进去,该怎么办呢?一般出现该问题基本是由于"WiFi密码不正确" ."Win7中保存的WiFi记录与路由器中不符&quo ...

  8. PHP:关于PHP商城秒杀防止超卖问题

    关于PHP商城秒杀防止超卖问题 序言: 在同样对数据操作的代码下,redis事务比lua脚本还要慢上许多,会偶尔出现1-10单超卖的现象. 如果想要使用redis事务,删减库存的情况,用redis-& ...

  9. 0x000000f怎么修复 win10_win10系统提示错误代码0xc000000f的三种解决方法

    在使用windows10正式版系统电脑过程中遇到了无法开机情况,而且提示0xc000000f的错误代码,此时该怎么办呢?其实,这一般是由于映像出现问题所引起的.下面,就随小编一起看看win10系统提示 ...

最新文章

  1. 深度|机器学习到底能替人干哪些工作?《科学》列出了8条评估标准
  2. 天梯赛 L1-025 正整数A+B (15 分)
  3. 关于intent-filter的误区
  4. c语言输入一段字符,C语言实现输入一个字符串后打印出该字符串中字符的所有排列...
  5. 语句作用_3分钟短文:Laravel模型作用域,为你“节省”更多代码
  6. 【渝粤题库】广东开放大学 PHP动态网站设计 形成性考核
  7. 49 - 算法 - LeetCode 110 平衡二叉树 - 求二叉树的高度 -双重递归
  8. spring+mybatis 多数据源切换
  9. 对蚊子个人博客进行了彻底的改造
  10. 代码设计的几个基础技巧
  11. 电影院售票系统mysql表格_电影院售票数据库系统设计.doc
  12. 惠普打印机136w硒鼓芯片怎么清零_HP惠普打印机清零技巧
  13. App后台开发(学习笔记)
  14. matlab求多元函数微积分,基于Matlab软件求解多元函数积分
  15. 倒计时1天,IMG、完美、腾讯技术大咖相聚直播间详解光线追踪技术
  16. 【软件定义汽车】AUTOSAR架构介绍
  17. python的反转_Python 反转
  18. 官方:2056名广西考生未按规定上传“软考报考材料”,逾期将取消资格
  19. 你写一个web网页小游戏
  20. FFMPEG音频解码浅析

热门文章

  1. GBDT与XGB的异同
  2. 深入浅出JMS(一)–JMS基本概念(转载)
  3. html5画时钟为什么不显示不出来,用html5绘制的时钟为什么无法显示
  4. 奇文共赏(经典博客总结)
  5. php js获取class,用jquery如何获取类名
  6. 40岁以后的程序员还能做什么?
  7. 视频教程-跟着王进老师学开发Python篇:基础入门案例讲解-Python
  8. 单片机课程设计数字心率计_基于单片机的数字心率计设计
  9. 805计算机知识综合,2017年中南林业科技大学计算机与信息工程学院805高级程序设计语言考研题库...
  10. 0基础交大慧谷python培训