宝家-秒杀模块-业务分析参考

1. 秒杀模式介绍

秒杀卖场一直是电商项目中最热门的存在,其目的就是以超低价格商品吸引消费者参加活动。这是一种很常见的促销方式。在电商中秒杀的销售模式最大的挑战就是我们需要面临短时间段的恐怖并发流量,因为存在时间和库存的限制,参与秒杀的用户会在固定的时间段访问我们的服务器,突然的高并发流量如果不经过处理很有可能造成系统崩溃。

注意,这里需要明白的是,秒杀只是网站营销的一个活动,如果因为秒杀而导致整个服务器瘫痪不能使用,得不偿失。介于秒杀的特殊性,我们一般会将秒杀模块独立出来,单独的运行一个微服务,使用独立域名,将它与其他功能隔离开,避免影响到网站正常功能的使用。

2. 场景分析

**秒杀业务的原则就是处理高并发,保证系统不被拖垮,并且尽可能快的处理所有请求。**首先,我们需要把请求尽量的拦截在系统上游,减少真正达到应用服务器的请求。

  • 用户在秒杀开始前,通过不停的刷新页面以保证不会错过秒杀。这些流量如果是访问应用服务器,连接数据库的话,会给服务器和数据库造成负载压力。

    针对这种场景我们的处理方案有两种:

    1. 重新设计秒杀详情页,将秒杀详情页静态化到nginx中,让nginx去处理这些静态资源的请求。但是这里有一点需要注意,我们秒杀详情页中的抢购按钮必须到秒杀时间才能点击,时间未到我们将按钮显示灰色无法点击。
    2. **(我们项目中使用的方案)**在第一次请求秒杀商品列表的时候,将秒杀商品存放到redis中,这样后面的所有请求秒杀商品的信息都可以由redis去处理。redis的数据在内存中,让redis去处理这种高并发场景比mysql效率高很多。而且秒杀商品一般都有限制每个用户只能抢购一次,也就是说每个用户只有一次写数据的请求,大多数都是读取数据,这种频繁的数据读取的场景刚好适用redis。
    3. 需要注意的是,有一些高端用户可能会直接去请求抢购下单的url,这种类似于作弊的行为也需要考虑,我们可以将url动态化。办法就是在下单页面url加入由服务器生成的随机数作为参数,让参数在秒杀开始时才能被得到。这个随机数只会产生一个,服务器端可以使用redis来存储这个参数。
  • 多台服务器处理下单请求的时候需要做一个前置检查:

    • 如果当前服务器已成功处理十个下单请求,那么对于后面的请求,直接返回结束页面。
    • 如果当前所有服务器已成功处理的等同于秒杀商品数量的请求,那就相当于,所有商品都已被下单,此时后面的请求全部返回结束页面。
  • 秒杀商品是定时上架的,通常来说我们不管在前端还是后台都会对时间进行严格把控,防止有人作弊,提前秒杀。定时秒杀还需要注意避免商家在秒杀前对商品进行编辑,从而造成不可预期的影响,所以我们还需要禁止商家在秒杀前进行秒杀商品的编辑。当然如果是数据出现错误,商家可以走数据订正的流程,由运营商来订正数据。

  • 目前市场上有许多针对于秒杀的秒杀器的使用,秒杀器下单及其迅速,堪称作弊利器。我们可以通过校验码的方式来应对秒杀器。一般采用的有:秒杀专用验证码,秒杀答题等。

3. 业务分析

秒杀的限制有两个,一个是时间,一个是库存。

  • 秒杀开始前,我们将秒杀商品存放到redis中,将所有查询秒杀商品信息的请求交给redis处理。并且我们需要禁止商家对秒杀商品的编辑。

  • 秒杀开始时,用户点击抢购进入填写订单页面,此时我们会将redis中对应商品的数量减一操作,并将订单信息存放到redis中。等到用户支付订单后,我们再将订单信息写入数据库,并修改秒杀商品的库存量。

    • 通常情况库存会带来超卖订单问题,也就是售出数量大于库存数量。我们在修改库存量的时候--------

      1.乐观锁

      update  seckills set count=#扣减后的库存量 where goodsId=#goodId and count=#扣减前的库存量
      

      2.尝试扣减库存操作**(我们项目中使用的方案)**

      update  seckills set count=count-#扣减库存数 where goodsId=#goodId and count>=#扣减库存数
      
  • 由于请求并发量太大,且秒杀一开始99.9%的请求都是下单请求,我们需要一个并发请求队列去保证请求的有序性。

    这里我们可以将下单的并发请求放到一个并发队列中,处理请求之前进行一个预处理—判断redis中还有库存时,如果有,再拿取下一个请求进行下单处理。(也可以在后台再次进行一个用户重下单的判断,如果是已经下过单,返回失败)

    • java的并发包提供了三个常用并发队列的实现:

      ConcurrentLinkedQueue:入队无锁,出队加锁。

      LinkedBlockingQueue:阻塞型,入队出队都加锁。

      ArrayBlockingQueue:初始量固定,阻塞型

    • 我们这里选用ConcurrentLinkedQueue实现请求队列,因为系统入队请求远大于出队请求。

前台设计

秒杀开始前某个时间到秒杀开始的时间段,被称为准备阶段。秒杀开始到所有用户获得秒杀结果是秒杀阶段。

  • 在准备阶段,用户会不停的刷新页面。前端需要保证秒杀页面的抢购按钮只有在固定时间才能被点击,并且秒杀页面和下单页面都尽可能的简单设计,减少不必要的网络开销。

  • 秒杀页面需要有秒杀倒计时的显示,这个一般是由js调用客户端本地时间。

  • 当用户点击下单或者购买之后,按钮变成灰色,js限制用户在x秒内只能提交一个请求。

  • 下单数量只能为1且不可修改。送货的地址和收件信息使用默认信息,允许提交订单后修改。

  • 用户第一次提交的订单成功后,再次点击只能看到抢购结束页面。

    • 针对非正常访问,例如某些人写一个for,不停的对服务器发起http请求,我们需要限制同一个uid,或者对同一个item的查询的访问频率,做页面缓存,x秒内的所有请求都返回同一个页面。

5. 流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SsLloGXi-1622031526747)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210507202321060.png)]

6.设计思路分析与总结

我们整个秒杀业务中,业务流程很简单,全部围绕着利用缓存分担数据库压力。而这个模块中最重要的是如何在秒杀前准备阶段和秒杀阶段快速且安全的处理高并发流量。

初步设想是让nginx通过静态资源分担后台应用的压力,但是这样会暴露我们下单的url,所以我们需要做一个特殊处理,给下单的url设置一个参数,由系统随机生成字符串,存储到redis中,在秒杀开始时再将redis中的字符串查询出来,传递给前端,形成一个固定的完整的下单url。(所有人看到的都会是同一个url,但是在秒杀开始之前,所有人都不会知道参数是什么,也就是url不完整,避免一些程序员提前下单)

不过通过nginx分担流量有个问题,我们生成的是静态页面,其中的库存量显示是秒杀前的。那我们在秒杀阶段再访问这个详情页就无法动态显示我们的库存量。(目前没有想到解决方案,先放这里,当然,如果不用实时显示库存量就没有这个问题)

秒杀开始时为了快速处理用户请求,我们的初步设想是做一个并发请求队列,所有请求都进到队列中。这里进一步优化设想是针对每个秒杀商品做出多个并发请求队列,我们的秒杀商品不止一个,如果只做一队列,就等同与对所有商品的下单请求全部放一起了,我们无法进行准确判断,只能一个个请求去处理。但是如果是一个队列处理一种商品的下单请求,我们就能很明确的知道,这个队列全是对a商品的下单操作。而这么做的好处是,作为服务端,我们很明确自己的a商品库存量有多少,假设库存量十件,我们可以将队列大小设置为固定的二十个容量,其他没有进入队列的全部返回已售罄。这样可以避免后面的用户长时间等待请求处理后,得到一个下单失败的信息,影响体验。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5y9uBRFg-1622031526751)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210507211433486.png)]

需要注意的是,我们的大队列可以使用java并发队列的ConcurrentLinkedQueue,这个队列的特点就是入队快,出队需要上锁。

而分队列可以使用ArrayBlockingQueue,它的初始量固定,属于阻塞性队列。

这种方案下相当于我们进行了一个下单请求的筛选,将没有可能下单成功的请求全部直接返回失败,不给他们请求下单接口的机会,也最大程度上节省了系统资源。

再然后就是处理筛选后有可能下单成功的请求了,这个请求数量我们在上图是放宽了限制了,以上面举例的,请求数是库存量倍数的情况下,肯定会有一半的人下单失败。而且我们是多个微服务进行下单操作,这里扣减redis的库存–下单操作必须加上分布式锁

分布式锁以redis实现。(详细查看分布式锁)

下单后需要将用户转至支付页面,提醒一分钟内支付,如果我们一分钟内没有接收到用户的成功支付信息,我们会将这个订单取消,库存回滚一个。并返回秒杀失败信息。

一旦用户成功支付,我们就确定他秒杀成功,直接返回结果,不需要等待信息录入mysql数据库。因为基于秒杀快速返回的原则,录入数据库这个跟用户无关,我们只要确定用户秒杀成功或者失败,就立马返回结果,剩下的业务交给系统慢慢处理。

秒杀模块-业务分析参考相关推荐

  1. 高并发核心编程Spring Cloud+Nginx秒杀实战,秒杀业务的参考实现

    秒杀业务的参考实现 本节从功能入手重点介绍Spring Cloud秒杀实战业务处理的3层实现:dao层.service层.controller层. 秒杀的功能模块和接口设计 秒杀系统的实现有多种多样的 ...

  2. SSM项目秒杀系统---(一)业务分析与Dao层

    文章目录 一.相关技术介绍 1.MySQL 2.MyBatis 3.Spring 4.SpringMVC 5.前端 6.高并发 二.创建项目和依赖 1.使用idea直接创建maven项目,使用mave ...

  3. JavaWeb电商 秒杀业务分析

    商品秒杀功能的高并发解决方案 一.业务逻辑分析 ​ 所谓秒杀: 从业务角度看,是短时间内多个用户"争抢"资源,这里的资源在大部分秒杀场景里是商品:将业务抽象,技术角度看,秒杀就是多 ...

  4. 转:秒杀系统架构分析与实战

    原文出处: 陶邦仁   欢迎分享原创到伯乐头条 0 系列目录 秒杀系统架构 秒杀系统架构分析与实战 1 秒杀业务分析 正常电子商务流程 (1)查询商品:(2)创建订单:(3)扣减库存:(4)更新订单: ...

  5. 秒杀系统架构分析与实战,一文带你搞懂秒杀架构!

    作者丨猿码道 jianshu.com/p/df4fbecb1a4b 1.秒杀业务分析 正常电子商务流程 (1)查询商品: (2)创建订单: (3)扣减库存: (4)更新订单: (5)付款: (6)卖家 ...

  6. 不错的秒杀系统架构分析与实战!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 猿码架构 来源 | https://urlif ...

  7. 【转】秒杀系统架构分析与实战

    0 系列目录 秒杀系统架构 秒杀系统架构分析与实战 1 秒杀业务分析 正常电子商务流程 (1)查询商品:(2)创建订单:(3)扣减库存:(4)更新订单:(5)付款:(6)卖家发货 秒杀业务的特性 (1 ...

  8. 热点推荐:秒杀系统架构分析与实战--转载

    原文地址:http://developer.51cto.com/art/201601/503511.htm 互联网正在高速发展,使用互联网服务的用户越多,高并发的场景也变得越来越多.电商秒杀和抢购,是 ...

  9. 限时抢购秒杀系统架构分析与实战

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

最新文章

  1. 用计算机问你叫什么名字,计算器女友与男子谈情说爱 一分钟发出各种甜言蜜语...
  2. Microservice 微服务的理论模型和现实路径
  3. Win64 驱动内核编程-26.强制结束进程
  4. 自定义圆环progressbar
  5. mysql5.7.20非安装版_mysql 5.7.20\5.7.21 免安装版安装配置教程
  6. vim中的jk为什么是上下_JK轮胎的完整形式是什么?
  7. RPM包制作及yum仓库搭建
  8. 4.2 js没有块级作用域
  9. 小雷:我的核心定位和远大志向(上次更新2013年11月9日)
  10. Trend Micro officescan隔离删除文件恢复
  11. 软件测试人员必备的60个测试工具清单,果断收藏了!
  12. texstudio设置暗黑主题
  13. Python当前时间是一年中第几周
  14. git提交规范图-提问的智慧图谱-React 学习路线图- 达克效应
  15. 学游戏原画的步骤是什么?超适合小白的学习方法
  16. 《MEMDOG:一种基于 Linux 的在线内存检测器》
  17. 关于工业物联网的10个笑话
  18. 鸿蒙系统有哪些手机可以应用,鸿蒙系统手机有哪些
  19. ios epub电子书阅读器demo
  20. SSD系列算法扩展与优化

热门文章

  1. 王伟storm_美国911事件后中国网民的反应(实录)
  2. 财报前瞻 | 开启餐饮业序幕,麦当劳Q4财报能否带来强劲指引?
  3. STM32F0系列FOC 源代码, 有单电阻采样和三电阻采样两种代码
  4. 什么是闭包,原理,优缺点以及应用场景
  5. 虚幻竞技场脚本源码V1.2公布
  6. 全连接层的顺序是先通道还是先_空调连接管路扩口及焊接方法。
  7. jQuery 发起 Ajax 请求最常用的三个方法
  8. PHP处理微信支付成功后的回调处理
  9. css 并排放置两个div
  10. 企业和个人拥有专利的好处,你绝对想不到