开发者社区> crazyacking> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

关于秒杀和超卖的性能问题

简介: 一、秒杀带来了什么?     秒杀或抢购活动一般会经过【预约】【抢订单】【支付】这3个大环节,而其中【抢订单】这个环节是最考验业务提供方的抗压能力的。 抢订单环节一般会带来2个问题:   1、高并发   比较火热的秒杀在线人数都是10w起的,如此之高的在线人数对于网站架构从前到后都是一种考验。
+关注继续查看

 

一、秒杀带来了什么?

 


 

秒杀或抢购活动一般会经过【预约】【抢订单】【支付】这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:

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

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

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

 

解决方案4:

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

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

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

 

三、总结


 

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

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

 

四、非技术感想


 

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

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

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

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

 

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
从零开始打造简易秒杀系统(一):防止超卖
本文主要是通过实际代码讲解,帮助你一步步搭建一个简易的秒杀系统。从而快速的了解秒杀系统的主要难点,并且迅速上手实际项目。
0 0
【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!
在电商领域,存在着典型的秒杀业务场景,那何谓秒杀场景呢。简单的来说就是一件商品的购买人数远远大于这件商品的库存,而且这件商品在很短的时间内就会被抢购一空。 比如每年的618、双11大促,小米新品促销等业务场景,就是典型的秒杀业务场景。
0 0
秒杀系统
秒杀能够以极小的经费撬动巨大的流量,虽然会带来一定的口碑损失,但因为极具性价比,所以经常被运营同学使用。本文介绍如何设计一款能够支撑60W QPS的秒杀系统,希望能够帮助到大家。
0 0
高并发秒杀系统如何实现正确的扣减库存?
高并发秒杀系统如何实现正确的扣减库存?
0 0
高并发秒杀系统如何实现正确的扣减库存?
在【精通高并发系列】的《实践出真知:全网最强秒杀系统架构解密!!》一文中,冰河详细的阐述了高并发秒杀系统的架构设计,也简单提到了如何扣减商品的库存。
0 0
不敢相信! 两个方案搞定了秒杀系统……
生活中有很多秒杀的情景, 例如商家促销, 像一元抢茅台, 五毛钱抢宝马(这儿只是一个例子), 假如一百万人来抢十瓶茅台, 这时候肯定不能多卖出, 也就是不能被大于10的人数抢到, 通常最后时间会有一个倒计时按钮, 30...29...28......3...2...1 GO! 之后跃跃欲试的人们开始抢。
0 0
高并发下秒杀商品,你必须知道的9个细节
高并发下秒杀商品,你必须知道的9个细节
0 0
秒杀场景浅析
Redis 秒杀 分布式锁
747 0
+关注
crazyacking
PaaS技术、Kubernetes、云计算,架构设计、数据库、数据结构、Unix/Linux编程
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Redis 的高并发实战:抢购系统
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载