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

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

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

  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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 从Excel中读取时间数据

之前写到从Excel中读取时间数据 //读取Excel数据Excel.Application xapp new Excel.Application();string filepath txt_Excel.Text;Excel.Workbook xbook xapp.Workbooks._Open(filepath, Missing.Value, Missing.Value,Missing.Value, Missing.Value, Missing.Value, Miss…

grid autosport额外内容下载慢_清理大王app下载-清理大王v1.0安卓下载

清理大王,下面由小编给大家介绍一下这款软件,该软件是一款非常不错的手机清理服务应用软件,清理大王app为用户提供了手机垃圾清理,内存加速,优化手机,解决手机卡顿的情况。感兴趣的朋友欢迎使用微侠下载&am…

怎么看cudnn的版本好_祖坟风水怎么看,好祖坟有什么征兆?

人们之所以看重祖坟的风水,是因为祖坟的风水与后代子孙的运势密切相关,可以说祖坟的风水好不好关系着子孙后代的运势顺不顺,因此对于祖坟的风水好坏人们是非常在意的,那么祖坟风水怎么看,好祖坟有什么征兆呢?下面是小编…

Spark 宽依赖和窄依赖

2019独角兽企业重金招聘Python工程师标准>>> 我们知道RDD就是一个不可变的带分区的记录集合,Spark提供了RDD上的两类操作,转换和动作。转换是用来定义一个新的RDD,包括map, flatMap, filter, union, sample, join, groupByKey, co…

smart gesture安装失败_WinCC flexible SMART V3 SP2安装步骤以及常见错误解决方法

1安装配置1. win7和win10系统都可以装2. 运行内存至少要2G。3. 硬盘储存空间至少要3G。2安装注意事项1.安装本软件之前必须要关闭所有杀毒软件(例如360安全卫士/360杀毒/电脑管家)等。2.其它西门子软件不要使用或者打开。3.安装之前确保硬盘空间充足。3下载地址https://bbs.jcp…

启动页面和各设备的宽高比及像素

2019独角兽企业重金招聘Python工程师标准>>> iOS7只能用LaunchImage来布置启动画面,只能用图片。iOS8以后支持LaunchScreen.xib来布置,可以自己添加控件。iOS8以及以后的用LaunchScreen来配置启动页。iOS8以后的会走这个设置,而io…

cc压力测试_中小型网站如何防范CC攻击?

大公司就不说了,付费CDN,防火墙,WAF,大流量,一般也会配置专门的安全问题响应团队。今天侧重讨论一下中小型网站如何(优雅)防范CC攻击。中小站点安全问题通病:对安全问题不重视&#…

泛型复习

回顾泛型类 泛型类&#xff1a;具有一个或多个泛型变量的类被称之为泛型类1、class A<T>{} 2、在创建泛型实例时&#xff0c;需要为其类型变量赋值A<String> anew A<String>(); *如果创建实例时&#xff0c;不给类型变量赋值&#xff0c;那么会有一个警告&am…

.net core EPPlus npoi_2020 ASP.NET界面开发:DevExpress v20.1支持.NET Core设计时

DevExpress ASP.NET Web Forms Controls拥有针对Web表单(包括报表)的110种UI控件&#xff0c;DevExpress ASP.NET MVC Extensions是服务器端MVC扩展或客户端控件&#xff0c;由轻量级JavaScript小部件提供支持的70个高性能DevExpress ASP.NET Core Controls&#xff0c;包含功能…

mac电脑如何与手机同步复制粘贴_如何将电脑里的文件同步到手机里?

由于PDF的特殊性&#xff0c;一般很少有适用于手机编辑的软件&#xff0c;所以我们都习惯于使用电脑来修改PDF文档后&#xff0c;再发送到手机微信发送给其他人&#xff0c;那么如何快速将电脑里的PDF文件同步到手机里面呢&#xff1f;可能很多人会想到使用各种云盘&#xff0c…

走进缓存的世界(一) - 开篇

系列文章 走进缓存的世界&#xff08;一&#xff09; - 开篇走进缓存的世界&#xff08;二&#xff09; - 缓存设计走进缓存的世界&#xff08;三&#xff09; - Memcache概述 对于程序员来说多多少少都懂一点算法&#xff0c;算法是什么&#xff1f;算法是“时间”与“空间”的…

an 转换器_400V耐压场效应管替代IRF730B型号参数,使用在DC-DC电源转换器。_场效应管吧...

DC-DC电源转化器的应用场景逐渐广泛&#xff0c;那么适用于DC-DC电源模块的场效应管需求也随之越来越高&#xff0c;这时候电源转化器厂的电子工程师就要留意了&#xff0c;国内是否有优质的场效应管能替代IRF730B型号呢&#xff0c;其实是有的&#xff0c;FHP840其实是可以跟I…

spring MVC中页面添加锚点

2019独角兽企业重金招聘Python工程师标准>>> 需要添加锚点的代码&#xff1a; <li><a href"main/index#page1">推荐车型</a></li> <li><a href"main/index#page2">热门车型</a></li>需要跳转的…

steam一键授权工具_半个东的时间让你省了一个亿 Steam免费游戏一键领取

总所周知Steam上有很多的免费游戏&#xff0c;但是有哪些游戏是免费的呢&#xff1f;这个一时半会儿也总结不出来&#xff0c;而且还得需要大量的时间添加到自己的游戏库&#xff0c;今天这个教程就教大家如何一键添加Steam上大量免费游戏&#xff0c;需要的小伙伴赶紧收藏哦。…

YModem协议

源&#xff1a;YModem协议 YModem协议&#xff1a; YModem协议是由XModem协议演变而来的&#xff0c;每包数据可以达到1024字节&#xff0c;是一个非常高效的文件传输协议。 下面先看下YModem协议传输的完整的握手过程&#xff1a;先看下图 SENDER:发送方。 RECEIVER:接收方。 …

gcc、clang、make、cmake、makefile、CMakeLists.txt概念学习

说明 编译器是翻译代码为计算机语言的一个工具&#xff0c;我们平时写的代码如果想在某个特定的计算机上执行&#xff08;计算机的cpu构架不同&#xff09;&#xff0c;就需要编译器来对代码进行编译汇编链接&#xff0c;而汇编和链接的过程对于每个不同的平台上过程都不一样。…

视觉在无人驾驶中的应用及分类_机器视觉在智能化生产中的广泛应用

什么是机器视觉&#xff1f;顾名思义&#xff0c;简单来说&#xff0c;机器视觉就是用机器代替人眼来测量和判断。机器视觉系统是指通过机器视觉产品将被摄取目标转换成图像信号&#xff0c;传送给专用的图像处理系统&#xff0c;根据像素分布和亮度、颜色等信息&#xff0c;转…

Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程。在该例程序中&#xff0c;使用"Ctrlc"结束通信后&#xff0c;服务器是无法立即重启的&#xff0c;如果尝试重启服务器&#xff0c;将被告知&#xff1a; bind: Address already in use 原因在…

work2的code和问题

//常量 package cn.itcast.work2; public class Constant { //constant 常量   public static void main(String[] args) { /* * 字符串常量 用双引号括起来的内容 * 整数常量 所有整数 * 小数常量 所有小数 * 字符常量 用单引号括起来的内容,里面只能放单个数字,单个字母或单…

Linux-(C/C++)生成并使用静态库/动态库

静态库/动态库概要 在Windows下静态库的后缀为&#xff1a;.lib、动态库后缀为&#xff1a;.dll&#xff1b;而在Linux下静态库的后缀为&#xff1a;.a、动态库的后缀为&#xff1a;.so。 那么什么是静态库呢&#xff1f; 首先我们来看看程序编译的大体流程&#xff1a;预处理…