`

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

 
阅读更多

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

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

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:

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

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

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

解决方案4:

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

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

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

三、总结


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

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

四、非技术感想


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

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

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

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

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

 

其它相关文章:

淘宝超卖现象的产生及解决方案

分享到:
评论

相关推荐

    Redis的类库及Redis解决订单秒杀超卖问题,极光推送代码

    在本文中,我们将重点讨论Redis的类库、String类型的应用,以及如何利用Redis来解决订单秒杀超卖的问题。同时,还会涉及C# .Net Core下极光推送的代码实现。 首先,让我们来看看C# .Net Core下如何使用Redis的类库...

    Java秒杀系统方案优化 高性能高并发实战

    通过上述讨论我们可以看出,在构建一个高性能高并发的秒杀系统过程中,合理选择技术栈和架构设计至关重要。同时还需要关注细节上的优化以及应对突发情况的能力。只有这样才能够保证在海量用户访问时仍能保持良好的...

    一个秒杀例子的分析, 秒杀系统的分析

    在这个分析中,我们将探讨如何使用Python语言来设计和实现一个秒杀系统,并结合实际的毕业设计场景进行深入讨论。 首先,秒杀系统的核心挑战在于处理高并发和数据一致性。在Python中,可以使用Tornado或Sanic等异步...

    秒杀网站源码

    9. **监控与日志**:通过Prometheus、Grafana等工具进行系统监控,及时发现并解决问题。同时,完整且有效的日志记录是定位问题的关键,使用Logback、Log4j等日志框架进行日志收集和分析。 10. **测试与压测**:在...

    电商秒杀项目实战.rar

    在电商行业中,秒杀活动是一种常见的促销手段,它能在短时间内吸引大量用户参与,提升商品销量。本电商秒杀项目实战教程旨在帮助开发者...同时,这也是一个很好的团队协作和交流的平台,欢迎更多开发者参与学习和讨论。

    某课秒杀系统源码,SpringMVC+Spring+Mybatis

    1. **并发控制**:秒杀活动往往伴随着高并发,因此需要处理好请求的并发问题,防止超卖。可以采用分布式锁(如Redis锁)、乐观锁(版本号机制)或悲观锁(数据库行锁)等方式。 2. **流量削峰**:预先设置限流策略...

    Java高并发秒杀API之业务分析与DAO层

    在这个主题下,我们主要讨论两个关键部分:业务分析和DAO(Data Access Object)层的设计。 首先,业务分析是任何系统设计的起点。秒杀活动通常在电商、票务等场景中出现,如限时抢购、特价商品或热门演出门票。这...

    SpringBoot构建电商秒杀项目-miaosha.zip

    接下来,我们将详细讨论这个项目中涉及的关键技术点和实现原理。 1. **SpringBoot基础**: SpringBoot简化了Spring应用的初始搭建以及开发过程,它集成了大量的Spring生态系统中的组件,如Spring MVC、Spring Data...

    java秒杀项目源码-seckill:Java高并发秒杀API之业务分析与DAO层源码和整理的笔记seckill是项目源码note是整理的笔记

    这里我们将围绕"java秒杀项目源码-seckill"这个项目进行详细的分析和讨论。 首先,`seckill`项目源码是基于Java实现的秒杀系统的业务层代码,包含了处理秒杀业务的核心逻辑。项目中通常会包含以下几个关键模块: 1...

    redis使用watch秒杀抢购实现思路

    在IT行业中,尤其是在高并发场景下,秒杀和抢购活动是常见的促销手段,而...然而,这个解决方案还需要考虑其他因素,如并发控制、防止恶意刷单、以及数据库与Redis之间的数据同步等问题,以构建一个完整的秒杀系统。

    从 0 开始带你成为消息中间件实战高手.zip

    和 "43 秒杀系统的技术难点以及秒杀商品详情页系统的架构设计-watermark.pdf" 文件关注的是高并发场景下,如秒杀活动,如何利用消息队列构建高性能的系统架构,以及如何保证库存的准确扣减,防止超卖。 "21 设计...

    今日头条Java面试题集

    在秒杀场景下,面试可能会讨论如何处理高并发下的订单创建、库存扣减、防止超卖等问题,涉及到分布式锁、队列、数据库事务控制等技术。 【JVM调优】 JVM是Java程序的运行环境,面试中可能会涉及JVM内存模型(堆内存...

    PHP并发场景的几种解决方案.docx

    在PHP中,处理并发场景是一项挑战,特别是在秒杀、抢购等高并发业务中,防止超卖和确保数据一致性至关重要。以下将详细讨论两种常见的PHP并发解决方案:利用Redis事务特性和使用文件排他锁。 首先,我们可以利用...

    分布式锁三种实现方式及对比

    通常通过增加版本号字段来实现,例如在抢购、秒杀场景中防止超卖。 2. **基于缓存(如Redis)实现分布式锁** - **Redis命令实现**:使用`SETNX`命令尝试设置键值,只有键不存在时才会成功;`EXPIRE`设置超时时间...

    seckill

    秒杀系统是电商领域常见的一种促销手段,它能够在短时间内吸引大量用户参与,对系统的稳定性和性能提出了极高的要求。在本项目"seckill"中,我们可以看到与Java相关的技术实现,特别是结合AOP(面向切面编程)和...

Global site tag (gtag.js) - Google Analytics