2019独角兽企业重金招聘Python工程师标准>>>

最近业务试水电商,接了一个秒杀的活。之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己理论结合实际一次了。

  ps:进入正文前先说一点个人感受,之前看淘宝的ppt感觉都懂了,等到自己出解决方案的时候发现还是有很多想不到的地方其实都没懂,再次验证了“细节是魔鬼”的理论。并且一个人的能力有限,只有大家一起讨论才能想的更周全,更细致。好了,闲话少说,下面进入正文。

一、秒杀带来了什么?

  秒杀或抢购活动一般会经过【预约】【抢订单】【支付】这3个大环节,而其中【抢订单】这个环节是最考验业务提供方的抗压能力的。

  抢订单环节一般会带来2个问题:

  1、高并发

  比较火热的秒杀在线人数都是10w起的,如此之高的在线人数对于网站架构从前到后都是一种考验。

  2、超卖

  任何商品都会有数量上限,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的难题。

二、如何解决?

  首先,产品解决方案我们就不予讨论了。我们只讨论技术解决方案

1、前端

  面对高并发的抢购活动,前端常用的三板斧是【扩容】【静态化】【限流】

  A:扩容

  加机器,这是最简单的方法,通过增加前端池的整体承载量来抗峰值。

  B:静态化

  将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。

  C:限流

  一般都会采用IP级别的限流,即针对某一个IP,限制单位时间内发起请求数量。

  或者活动入口的时候增加游戏或者问题环节进行消峰操作。

  D:有损服务

  最后一招,在接近前端池承载能力的水位上限的时候,随机拒绝部分请求来保护活动整体的可用性。

2、后端

  那么后端的数据库在高并发和超卖下会遇到什么问题呢?主要会有如下3个问题:(主要讨论写的问题,读的问题通过增加cache可以很容易的解决)

  I: 首先MySQL自身对于高并发的处理性能就会出现问题,一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。

  II: 其次,超卖的根结在于减库存操作是一个事务操作,需要先select,然后insert,最后update -1。最后这个-1操作是不能出现负数的,但是当多用户在有库存的情况下并发操作,出现负数这是无法避免的。

  III:最后,当减库存和高并发碰到一起的时候,由于操作的库存数目在同一行,就会出现争抢InnoDB行锁的问题,导致出现互相等待甚至死锁,从而大大降低MySQL的处理性能,最终导致前端页面出现超时异常。

  针对上述问题,如何解决呢? 我们先看眼淘宝的高大上解决方案:

  I:  关闭死锁检测,提高并发处理性能。

  II:修改源代码,将排队提到进入引擎层前,降低引擎层面的并发度。

  III:组提交,降低server和引擎的交互次数,降低IO消耗。

  以上内容可以参考丁奇在DTCC2013上分享的《秒杀场景下MySQL的低效》一文。在文中所有优化都使用后,TPS在高并发下,从原始的150飙升到8.5w,提升近566倍,非常吓人!!!

  不过结合我们的实际,改源码这种高大上的解决方案显然有那么一点不切实际。于是小伙伴们需要讨论出一种适合我们实际情况的解决方案。以下就是我们讨论的解决方案:

  首先设定一个前提,为了防止超卖现象,所有减库存操作都需要进行一次减后检查,保证减完不能等于负数。(由于MySQL事务的特性,这种方法只能降低超卖的数量,但是不可能完全避免超卖)

update number set x=x-1 where (x -1 ) >= 0;

解决方案1:

  将存库从MySQL前移到Redis中,所有的写操作放到内存中,由于Redis中不存在锁故不会出现互相等待,并且由于Redis的写性能和读性能都远高于MySQL,这就解决了高并发下的性能问题。然后通过队列等异步手段,将变化的数据异步写入到DB中。

  优点:解决性能问题

  缺点:没有解决超卖问题,同时由于异步写入DB,存在某一时刻DB和Redis中数据不一致的风险。

解决方案2:

  引入队列,然后将所有写DB操作在单队列中排队,完全串行处理。当达到库存阀值的时候就不在消费队列,并关闭购买功能。这就解决了超卖问题。

  优点:解决超卖问题,略微提升性能。

  缺点:性能受限于队列处理机处理性能和DB的写入性能中最短的那个,另外多商品同时抢购的时候需要准备多条队列。

解决方案3:

  将写操作前移到Memcached中,同时利用Memcached的轻量级的锁机制CAS来实现减库存操作。

  优点:读写在内存中,操作性能快,引入轻量级锁之后可以保证同一时刻只有一个写入成功,解决减库存问题。

  缺点:没有实测,基于CAS的特性不知道高并发下是否会出现大量更新失败?不过加锁之后肯定对并发性能会有影响。

解决方案4:

  将提交操作变成两段式,先申请后确认。然后利用Redis的原子自增操作(相比较MySQL的自增来说没有空洞),同时利用Redis的事务特性来发号,保证拿到小于等于库存阀值的号的人都可以成功提交订单。然后数据异步更新到DB中。

  优点:解决超卖问题,库存读写都在内存中,故同时解决性能问题。

  缺点:由于异步写入DB,可能存在数据不一致。另可能存在少买,也就是如果拿到号的人不真正下订单,可能库存减为0,但是订单数并没有达到库存阀值。

三、总结

  1、前端三板斧【扩容】【限流】【静态化】

  2、后端两条路【内存】+【排队】

四、非技术感想

  1、团队的力量是无穷的,各种各样的解决方案(先不谈可行性)都是在小伙伴们七嘴八舌中讨论出来的。我们需要让所有人都发出自己的声音,不要着急去否定。

  2、优化需要从整体层面去思考,不要只纠结于自己负责的部分,如果只盯着一个点思考,最后很可能就走进死胡同中了。

  3、有很多东西以为读过了就懂了,其实不然。依然还是需要实践,否则别人的知识永远不可能变成自己的。

  4、多思考为什么,会发生什么,不要想当然。只有这样才能深入进去,而不是留在表面。

  ps:以上仅仅是我们讨论的一些方案设想,欢迎大家一起讨论各种可行方案。

转载于:https://my.oschina.net/u/131940/blog/732760

如何解决秒杀的性能问题和超卖的讨论相关推荐

  1. 如何解决秒杀的性能问题和超卖的讨论 及防止按钮多次点击

    抢购活动一般会经过[预约][抢订单][支付]这3个大环节,而其中[抢订单]这个环节是最考验业务提供方的抗压能力的. 抢订单环节一般会带来2个问题: 1.高并发 比较火热的秒杀在线人数都是10w起的,如 ...

  2. 秒杀的性能问题和超卖

    秒杀的性能问题和超卖 抢订单环节一般会带来2个问题: 1.高并发 2.超卖 二.如何解决? 1.前端 A:扩容 B:静态化 C:限流 D:有损服务 2.后端 针对上述问题,如何解决呢? 我们先看眼淘宝 ...

  3. 秒杀活动,提高性能,防止超卖,订单超时

    目录 初步思考 秒杀活动 订单防止超卖 订单超时如何处理 初步思考 原文地址 前端:页面尽可能静态化,css/js合并,减少请求数 扩容:增加机器,提高处理请求能力 限流:应用限流(nginx,tom ...

  4. 【Java秒杀方案】11.功能开发-【商品秒杀及优化】防止超卖 接口优化(redis预减库存,内存标记减少redis访问,RabbitMQ异步下单) 安全优化(隐藏秒杀接口,验证码,接口防刷)

    商品秒杀核心功能及优化 1. 正常秒杀流程 在商品详情页面等待秒杀倒计时–http://localhost:8080/goodsDetail.htm?goodsId=2 倒计时为0,开始秒杀,点[秒杀 ...

  5. 秒杀 mysql 事务_秒杀怎么样才可以防止超卖?基于mysql的事务和锁实现

    Reference:  http://blog.ruaby.com/?p=256 并发事务处理带来的问题? 相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从 ...

  6. java秒杀怎么防止超卖_秒杀系统是如何防止超卖的?

    秒杀系统介绍 秒杀系统相信网上已经介绍了很多了,我也不想黏贴很多定义过来了. 废话少说,秒杀系统主要应用在商品抢购的场景,比如: 电商抢购限量商品 卖周董演唱会的门票 火车票抢座 - 秒杀系统抽象来说 ...

  7. 解决秒杀系统超卖问题的三种方案

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

  8. Redis高并发场景下秒杀超卖解决

    目录 1 什么是秒杀 2 为什么要防止超卖 3 单体架构常规秒杀 3.1 常规减库存代码 3.2 模拟高并发 3.3 超卖现象 3.4 分析原因 4 简单实现悲观乐观锁解决单体架构超卖 4.1 悲观锁 ...

  9. 淘宝如何解决超卖问题

    这篇文章是我从某文库爬下来的,放在这里供大家学习. 淘宝超卖现象的产生及解决方案 一.什么是超卖现象?  超卖即"超卖缺货",当宝贝库存接近0时,如果多个买家同时付款购买此宝贝,将 ...

最新文章

  1. 在SharePoint 2010使用OWA查看自己邮箱的内容
  2. CentOS系统启动流程和系统初始化
  3. 播放生成Android4.0.3中的提示音
  4. ADSL掉线解决方法全略
  5. java ee的小程序_用微服务和容器替换旧版Java EE应用程序服务器
  6. 剑指Offer - 面试题57. 和为s的两个数字(双指针)
  7. POJ NOI MATH-7649 我家的门牌号
  8. jntoo.php,小舍微信分销拼团系统V6.0三级分销系统最新版源码+支持多商户入驻+拼团+微商城+分销...
  9. JAVA电影院售票系统毕业设计 开题报告
  10. 使用jxls模板解析导出数据时添加单元格样式
  11. sh: warning: setlocale: LC_ALL: cannot change locale (zh_CN.GB18030)
  12. 飞飞影视php 漏洞,飞飞影视SQL injection exploit[转]
  13. 简析美颜sdk中的人脸识别算法
  14. FULL JOIN 数据库全连接查询SQL
  15. ESLint+Prettier+Vetur 统一Vue项目代码风格
  16. iOS调试Bug技巧
  17. 【数据结构与算法】二叉树题目很难?一句话秒杀基础二叉树题目
  18. 2019计算机网络原理04741,04741计算机网络原理201910.doc
  19. kali linux 安装打印机的方法
  20. 云课堂智慧职教答案python_智慧职教云课堂Python程序设计答案公众号

热门文章

  1. 《剑指offer》全解(图文结合,通俗易懂,一篇看爽)
  2. leetcode181. 超过经理收入的员工(SQL)
  3. leetcode198 打家劫舍
  4. Redis:10---List对象
  5. python外卷(7)--glob
  6. 《Python Cookbook 3rd》笔记(1.15):通过某个字段将记录分组
  7. STL源码剖析 关联式容器 红黑树
  8. 以太坊账户 相关知识
  9. 新手课堂之汽车灯光操作及位置
  10. axios 发 post 请求,后端接收不到参数的解决方案