前言:高并发下如何设计出健壮的秒杀系统?比如淘宝和小米手机的秒杀活动。秒杀一般出现在商城的促销活动中,指定了一定数量(比如:10个)的商品(比如:手机),以极低的价格(比如:0.1元),让大量用户参与活动,但只有极少数用户能够购买成功。这类活动商家绝大部分是不赚钱的,说白了是找个噱头宣传自己。虽说秒杀只是一个促销活动,但对高并发场景下的后端多方面的知识要求不低。


一、秒杀促销活动应该考虑哪些问题?

1.1、库存超卖

分析秒杀的业务场景,最重要的有一点就是超卖问题,假如备货只有100个,但是最终超卖了200,一般来讲秒杀系统的价格都比较低,如果超卖将严重影响公司的财产利益,因此首当其冲的就是解决商品的超卖问题。

1.2、瞬时高并发

秒杀具有持续时间短和并发量大的特点,秒杀持续时间只有几分钟,而一般公司都为了制造轰动效应,会以极低的价格来吸引用户,因此参与抢购的用户会非常的多,短时间内会有大量请求涌进来。

一般在秒杀时间点(比如:双十一12点)前几分钟,用户并发量才真正突增,达到秒杀时间点时,并发量会达到顶峰。但由于这类活动是大量用户抢少量商品的场景,必定会出现狼多肉少的情况,所以其实绝大部分用户秒杀会失败,只有极少部分用户能够成功。正常情况下,大部分用户会收到商品已经抢完的提醒,收到该提醒后,他们大概率不会在那个活动页面停留了,如此一来,用户并发量又会急剧下降。所以这个峰值持续的时间其实是非常短的,这样就会出现瞬时高并发的情况,下面用一张图直观的感受一下流量的变化:

像这种瞬时高并发的场景,传统的系统很难应对,我们需要设计一套全新的系统。可以从以下几个方面入手:

  • CDN加速的页面静态化

  • 缓存

  • mq异步处理

  • 限流

  • 分布式锁

1.3、秒杀url的接口防刷

对于普通用户来讲,看到的只是一个比较简单的秒杀页面,在未达到规定时间,秒杀按钮是灰色的,一旦到达规定时间,灰色按钮变成可点击状态。这部分是针对小白用户的,如果是稍微有点电脑功底的用户,会通过F12看浏览器的network看到秒杀的url,通过特定软件去请求也可以实现秒杀。或者提前知道秒杀url的人,一请求就直接实现秒杀了。这个问题我们需要考虑解决。

现在的秒杀大多都会出来针对秒杀对应的软件,这类软件会模拟不断向后台服务器发起请求,一秒几百次都是很常见的,如何防止这类软件不断发起的的重复无效请求进行限流,是我们需要认真考虑的。

1.4、数据库设计

秒杀有把我们服务器击垮的风险,如果让它与我们的其他业务使用在同一个数据库中,耦合在一起,就很有可能牵连和影响其他的业务。如何防止这类问题发生,就算秒杀发生了宕机、服务器卡死问题,也应该让他尽量不影响线上正常进行的业务。

针对「数据库设计」提出的秒杀数据库的问题,因此应该单独设计一个秒杀数据库,防止因为秒杀活动的高并发访问拖垮整个网站。这里只需要两张表,一张是秒杀订单表,一张是秒杀货品表。

其实应该还有几张表,商品表:可以关联goods_id查到具体的商品信息,商品图像、名称、平时价格、秒杀价格等,还有用户表:根据用户user_id可以查询到用户昵称、用户手机号,收货地址等其他额外信息,这个具体就不给出实例了。


二、秒杀系统的设计和技术方案

2.1、秒杀页面静态化

活动页面是用户流量的第一入口,所以是并发量最大的地方。如果这些流量都能直接访问服务端,恐怕服务端会因为承受不住这么大的压力,而直接挂掉。活动页面绝大多数内容是固定的,比如:商品名称、商品描述、图片等。为了减少不必要的服务端请求,通常情况下,会对活动页面做静态化处理。用户浏览商品等常规操作,并不会请求到秒杀服务端。只有到了秒杀时间点,并且用户主动点了秒杀按钮才允许访问秒杀服务端。这样能过滤大部分无效页面请求。

但只做页面静态化还不够,因为用户分布在全国各地,有些人在北京,有些人在成都,有些人在深圳,地域相差很远,网速各不相同。为了性能考虑,一般会将css、js和图片等静态资源文件提前缓存到CDN上,它的全称是Content Delivery Network,即内容分发网络。让用户能够就近访问秒杀页面,降低网络拥塞,提高用户访问响应速度和命中率。

2.2、使用Nginx解决Tomcat接口并发问题

Nginx是一个高性能Web服务器,它的并发能力可以达到几万,而Tomcat默认连接数是1万。通过Nginx映射客户端请求,再分发到后台Tomcat服务器集群中可以大大提升并发能力。

2.3、读多写少使用Redis缓存

在秒杀的过程中,系统一般会先查一下库存是否足够,如果足够才允许下单写数据库。如果不够,则直接返回该商品已经抢完。秒杀是非常典型的读多写少场景,使用Redis做缓存再合适不过。

如果有数十万的请求过来,同时通过数据库查缓存是否足够,此时数据库可能会挂掉。因为数据库的连接资源非常有限,比如:MySQL无法同时支持这么多的连接。我们应该构建Redis集群,采用哨兵模式,可以提升Redis的高并发和高可用。

2.4、库存问题(重点)

对于库存问题看似简单,实则里面还是有些东西。真正的秒杀商品的场景,不是说扣完库存,就完事了,如果用户在一段时间内,还没完成支付,扣减的库存是要加回去的。

(1)Redis预减库存

很多请求进来,都需要后台查询库存,这是一个频繁读的场景。可以使用Redis来预减库存,在秒杀开始前可以在Redis设值,比如redis.set(goodsId,100),这里预放的库存为100可以设值为常量,每次下单成功之后,Integer stock = (Integer)redis.get(goosId); 然后判断sock的值,如果小于常量值就减去1;不过注意当取消的时候,需要增加库存,增加库存的时候也得注意不能大于之间设定的总库存数(查询库存和扣减库存需要原子操作,此时可以借助lua脚本)下次下单再获取库存的时候,直接从Redis里面查就可以了。

(2)库存超卖问题

在下单扣减库存的业务场景中,需要保证大流量、高并发下商品的库存不能为负。

(3)Redis分布式锁

如果在高并发下,有大量的请求都去查库存,会造成库存脏数据,所以必须得加分布式锁。

2.5、接口限流防刷

通过秒杀活动,如果我们运气爆棚,可能会用非常低的价格买到不错的商品(这种概率堪比买福利彩票中大奖)。但有些高手,并不会像我们一样老老实实,通过秒杀页面点击秒杀按钮,抢购商品。他们可能在自己的服务器上,模拟正常用户登录系统,跳过秒杀页面,直接调用秒杀接口。

如果是我们手动操作,一般情况下,一秒钟只能点击一次秒杀按钮。

但是如果是服务器,一秒钟可以请求成上千接口。这种差距实在太明显了,如果不做任何限制,绝大部分商品可能是被机器抢到,而非正常的用户,有点不太公平。

所以,我们有必要识别这些非法请求做一些限制。

目前有两种常用的限流方式:

  • 基于nginx限流

  • 基于redis限流

秒杀最终的本质是数据库的更新,但是有很多大量无效的请求,我们最终要做的就是如何把这些无效的请求过滤掉,防止渗透到数据库。限流的话,需要入手的方面很多:

(1)前端限流

首先第一步就是通过前端限流,用户在秒杀按钮点击以后发起请求,那么在接下来的5秒是无法点击(通过设置按钮为disable)。这一小举措开发起来成本很小,但是很有效。

(2)同一个用户xx秒内重复请求直接拒绝

具体多少秒需要根据实际业务和秒杀的人数而定,一般限定为10秒。具体的做法就是通过Redis的键过期策略,首先对每个请求都从String value = redis.get(userId);如果获取到这个value为空或者为null,表示它是有效的请求,然后放行这个请求。如果不为空表示它是重复性请求,直接丢掉这个请求。如果有效,采用redis.setexpire(userId,value,10).value可以是任意值,一般放业务属性比较好,这个是设置以userId为key,10秒的过期时间(10秒后,key对应的值自动为null)。

(3)对同一ip限流

有时候只对某个用户限流是不够的,有些高手可以模拟多个用户请求,这时需要用Nginx加同一ip限流功能。

(4) 加验证码

通常情况下,用户在请求之前,需要先输入验证码。用户发起请求之后,服务端会去校验该验证码是否正确。只有正确才允许进行下一步操作,否则直接返回,并且提示验证码错误。

此外,验证码一般是一次性的,同一个验证码只允许使用一次,不允许重复使用。

2.6、消息队列异步下单

我们都知道在真实的秒杀场景中,有三个核心流程:

而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。

于是,秒杀后下单的流程变成如下:

为了提升下单的效率,并且防止下单服务的失败。需要将下单这一操作进行异步处理。最常采用的办法是使用消息队列,消息队列最显著的三个优点:异步、削峰、解耦。这里可以采用RocketMQ,在后台经过了限流、库存校验之后,流入到这一步骤的就是有效请求。然后发送到队列里,队列接受消息,异步下单。下完单,入库没有问题可以用短信通知用户秒杀成功。假如失败的话,可以采用补偿机制,重试。

2.7、服务降级

假如在秒杀过程中出现了某个服务器宕机,或者服务不可用,应该做好后备工作。之前的博客里有介绍通过Sentinel进行服务熔断和降级,可以开发一个备用服务,假如服务器真的宕机了,直接给用户一个友好的提示返回,而不是直接卡死,服务器错误等生硬的反馈。


参考链接:

高并发下秒杀商品,你必须知道的9个细节

双十一秒杀架构模型设计

高并发秒杀系统如何实现正确的扣减库存?

高并发下的秒杀系统设计相关推荐

  1. 高并发下的秒杀系统架构设计实战!

    1.秒杀业务分析 正常电子商务流程 (1)查询商品: (2)创建订单: (3)扣减库存: (4)更新订单: (5)付款: (6)卖家发货: 秒杀业务的特性 (1)低廉价格: (2)大幅推广: (3)瞬 ...

  2. php 秒杀并发怎么做,PHP实现高并发下的秒杀功能–Laravel

    namespace App\Http\Controllers\SecKill; use App\Http\Controllers\Controller; use Exception; use Illu ...

  3. PHP实现高并发下的秒杀功能–Laravel

    namespace App\Http\Controllers\SecKill; use App\Http\Controllers\Controller; use Exception; use Illu ...

  4. redis抽奖并发_Redis优化高并发下的秒杀性能

    本文内容 使用Redis优化高并发场景下的接口性能 数据库乐观锁 随着双11的临近,各种促销活动开始变得热门起来,比较主流的有秒杀.抢优惠券.拼团等等. 涉及到高并发争抢同一个资源的主要场景有秒杀和抢 ...

  5. 高并发下商城秒杀活动的处理

    秒杀抢购活动是现在很多商城常见的营销手段,小米抢购.淘宝的整点免单.聚划算等都是成功的例子. 从简单处着手,秒杀是很好理解的:设置要秒杀的商品的数量,抢完为止.但是,实际应用中一瞬间的高并发压力.以及 ...

  6. 阿里最后一面,高并发下如何设计一个秒杀系统?

    近年来,随着"双十一"购物节和抖音等直播平台带货的热潮,大批促销活动涌现,「秒杀」这个词也越来越频繁地出现在我们的生活里. 除了那些头部的电商公司,某宝.某东,还有各种街.某说.某 ...

  7. 高并发下秒杀商品,你必须知道的9个细节

    前言 高并发下如何设计秒杀系统?这是一个高频面试题.这个问题看似简单,但是里面的水很深,它考查的是高并发场景下,从前端到后端多方面的知识. 秒杀一般出现在商城的促销活动中,指定了一定数量(比如:10个 ...

  8. php电商交押金的逻辑,PHP高并发下抢购、秒杀功能的超卖问题

    ​抢购.秒杀是电商系统比较常见的功能,高并发下一般需要解决两个问题: 高并发下数据库的压力 高并发竞争下出现超卖问题 对于第一个问题,一般可以通过缓存.分库分表.主从等可以解决,这儿主要说说超卖问题. ...

  9. PHP redis秒杀返回结果,php结合redis实现高并发下的抢购、秒杀功能

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...

  10. php结合redis实现高并发下的抢购、秒杀功能

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...

最新文章

  1. javer的表结构设计
  2. 初学Netty(杰哥好久不见)
  3. vue学习笔记(1)-组件通信
  4. kafka可靠数据传递
  5. Linux删除安卓温控,RK平台关闭温度控制降频功能
  6. LL(1)分析表的构造
  7. linux终端输入lsblk无命令,lsblk
  8. 轻轻松松统计代码行数
  9. 假设以邻接矩阵作为图的存储结构_学习数据结构第五章:图(图的存储方法)...
  10. new_picview_PicView图片浏览器
  11. 头歌实践平台:机器学习——支持向量回归
  12. openGL学习笔记七: glad库及使用
  13. 我们应该如何规划自己的一生?
  14. iOS苹果超级签苹果分发平台企鹅:422903005
  15. android 手机投屏电视,手机投屏到智能电视上的几种方法
  16. NFT - 2022年科技圈新宠
  17. 云服务器ECS使用记录-1. 介绍
  18. 凯哥自媒体:怎样用今日头条自媒体赚钱?
  19. oracle匹配excel数据,如何用Excel直接查询Oracle中的数据
  20. python处理MNIST数据集

热门文章

  1. 保研复习整理——数字信号处理
  2. 蓝牙技术谈之跳频技术(一)
  3. 高数教材班复习Hint(1.8-2.5)
  4. maven setting.xml详解
  5. 【黑马-SpringCloudAlibaba】学习笔记09-Nacos Config--服务配置
  6. A-PDF Watermark
  7. 项目进度相关计算总结
  8. ARQ协议与滑动窗口协议
  9. 百度人脸接口简单随笔
  10. 编程及C/C++初学者FAQ