什么是“秒杀”?为什么传统项目中也有“秒杀”的概念?一起来分析一下.

如题所述,到底什么是“秒杀”,为什么我不是做电商的,还和秒杀扯上关系了?

或者说“秒杀”一定是电商项目的一个关键字吗?

当然,笔者这样反问了,那么当然,秒杀就不是特定电商项目的事情了。可以将其理解为这一类的业务的一个代称。

哪一类业务呢?高并发项目。

举个行业的例子来说;(这里还是以电商项目为例,因为电商项目的并发场景比较便于理解)

双十一,是每个人都热血沸腾的时刻,为什么这里说是时刻呢?因为从我们技术人眼中,双十一不是一天的概念,而是那么一瞬间的概念,通常来说,我们比较关心双十一 0点的时候的一个流量情况,而不是关心一天的流量情况(当然,一天也得关心,此处相对而论);

从产品角度、用户角度而言,双十一是一个活动,一个通过各种红包、优惠价等方式形成的一种促销活动,这种活动,将会吸引用户大量购物,产生大量交易订单,从而带动经济流动,产生各种经济利益。

从技术角度而言,双十一产生的数据量也是庞大的,此处通过去年双十一一个图片表达。

这是历年的双十一当天的订单数量产生量,以2019年为例,一天的时间产生了2684亿元的成交量

,这当天的并发量是怎么评估的。

再看另一张图,这里统计的是突破1000亿耗时,用了64分钟成交金额1000亿,这并发量又是多少?

.

2秒不到产生了100亿的交易额

这种数据量的产生的流量高峰是什么样的高度,相信这都是行业能标杆的表现。

这里的并发量是真的不敢想象,我们简单的计算一下,1.36秒,产生了100亿的交易额。

假设1个订单平均是100块钱,那么1.36秒就是产生了 1亿的订单数

假设1个订单平均是1000块钱,那么1.36秒就是产生了 10000000的订单数

那么就可以认为 并发为 7,352,941/s

一秒 700多万的并发,试问这什么数据库,什么服务能承受得了?

此处再强调,700多万的并发量是站在有效订单生成的基础上计算而来,并且是估算1000元一个订单的平均成交额。

要知道,我们平时的抢购经验来说,基本上是一件商品,上千上万的用户在抢购,这个 700多万 应当 * 1000 都不为过。

那么给各位先分析了一个数据上的概念,我们对后面的分析可能会更加理解一些。

那么在这种情况,上万人抢购一件商品的库存,对于系统而言,如何承担这样大的压力,并且有多少这种抢购存在,对系统的负载又是一大考验。

从数据库层面,我们需要生成订单,减库存,这么大的并发请求,我们如何能保证一件商品,最终成交只会有一个订单,其他请求都抢购失败。我们如何保证我们能够保证系统能够正常处理这么大的并发抢购量,而不是导致此次抢购活动瘫痪,导致就连一个订单都没有生成?这些都是我们此次需要思考的问题。

对于数据而言,我们需要将库存 -1,然后生成一个订单数;这样才是正确的流程,并且库存只能是>=0,切不能成为负数。我们系统如何控制此种规则严格执行?在很多场景,很多顾客在抢购成功后,生成订单了,然后不想要了,就会取消订单,这个时候,我们需要将库存+1,吧这个名额给其他顾客继续抢购,那么这如何实现?是直接将库存加回去吗?

站在数据库层面,我们对于一件商品的库存数据,如果多个个顾客同时请求下单,这个时候,我们怎么处理这种多线程环境下,保证不会超出库存量?

每个用户都会去不停的刷新商品,不停地关注商品的库存量,想看看现在库存是否有,我是否能下单?这种高请求量的读请求和其他用户的高请求量的下单操作并发出现,我们如何控制一条数据读写操作并发环境下正常?那这种情况下,我们既要保证有序进行,又要保证系统的高吞吐性能?

上面抛出来了一些问题,我们接下来都会一一分析,一一思考解决方案;

对于上述问题,我们需要考虑整体的架构设计,因为对于一个系统的健壮性,不能单单考虑一个点,依赖于某个技术栈就能解决问题;

对于系统的健壮性,高可用,业务应用集群部署是少不了的,通常来说,一般的互联网项目,我们都是线上部署多个应用集群,通过负载均衡规则,将流量均摊给各个服务。保证整体业务的高可用。这是一种思路,但是我们今天从另外一个角度来分析一下系统优化。

很多后端程序员都会片面思考服务端如何优化,怎么保证系统的健壮,但是我认为这是不好的思维方式(虽然笔者侧重后端开发);作为一个优秀的程序员,应当有全局设计的思考能力。

通常来说,我们一个B/S应用结构,是由用户电脑的浏览器发起请求,然后由统一网关接收,然后将其路由至对应的服务应用上处理,然后服务应用访问数据库的数据。一个由上至下的层次访问方式。(应该不会有人问直接浏览器访问数据库吧?)画个图

很简单的一个架构方式,我们就需要对这图上的各个节点进行系统优化思考

用户的浏览器

对于顶层,直接和用户打交道的,通常交互应用是通过应用客户端,和浏览器网页等形式,在这层上,我们通常都会有一定的处理逻辑。H5上会有js脚本,控制整个网页的规则运行,APP上通常有类似java等语言处理逻辑。我们都是通过这些逻辑再与服务器进行交互请求,回调的。那么在此处,我们就需要限制用户的无意或者恶意操作了。例如,用户狂刷新商品,看看商品的最新库存(本质来说,这是很常见的用户操作行为,但是在笔者看来,这无意义人工压测了)。那么这种操作,我们就需要控制真正请求到后端的请求量了。如果客户端是一个吃瓜群众,用户操作多少下,就请求多少下,那么这个客户端开发就会被服务端打死。

我们会看到很多类似的场景,例如,一个下单按钮,我们会在正常发起了一个下单请求后,当服务端还未返回结果前,这个按钮就是置灰的,不允许点击的。这也是降频操作。

但是对于一些操作场景,读的场景,我们不可能说,用户去刷新商品的库存,一秒钟只能刷新一次(至少不能让用户这样感知),这个时候,我们就需要做一些特殊处理了。例如,采用客户端本地缓存,举例说明,对于某个商品的库存数据,客户端采用缓存,缓存的过期时间为2s,当缓存过期后,才再次真实的向服务端发起请求,那么原本用户在10s中共刷新了200下商品缓存,那么这个时候,其实只会发起5个请求到服务端,原本需要200个请求,拦截了大量的恶意用户操作请求。并且我们并不限制用户的操作,提高的用户的体验感。

平时我们也会看到很多抢购活动中,明明有库存啊,就是下单的时候,就告诉我,没货了。这其实就是缓存一致性问题导致的。这种问题都是我们故意制造出来的,因为在这种业务场景下,我们是不太特别严格要求数据的一致性的。

网关

上面关于普通的用户操作,我们是可以处理大部分的用户的恶意操作的。但是在一个合格的程序员面前,我们所考虑的用户并不都是那种"良好"操作习惯的用户。对于系统安全来说,我们还需要考虑“同行”的行为。

我们的12306抢票软件,都知道,我们很多人大多时候并不会真的在这个软件平台上进行购票操作,因为很多时候我们在上面看,基本上都是没票。

那么这个时候就衍生出来了很多“同行”的产品,例如“智行12306”、“美团抢票”等等,那么对于这种第三方平台所制作出来的应用,目的是什么?是为了保护"官方12306购票系统"吗?当然不是,他们的目的就是保证他们的付费用户能够高效的购买的心意的票。那么这个时候,就是不是用户与服务之间的较量了。这就是服务与服务之间的较量了。并且这种第三方应用很多,这个时候又变成“多个打一个”了。你觉得"官方12306购票系统"难不难?这也是为什么早期"官方12306购票系统"上线的时候,直接崩了的原因了。

那么"官方12306购票系统"怎么处理呢?不管你还是“智行12306”、“美团抢票”,你都需要登录吧?不登录,你还想抢票?当游客吗?那么这个时候,我们就可以有效的过滤一批请求了。我们的 12306账户都是实名制的,一个真实的合法公民只能有一个账号,绑定了我们的身份证,那么这个时候,我们就能确定一个用户发起的所有请求是否只是一个用户发起的,我们就可以针对这个用户进行精准限流了,在用户发起下单请求的时候,都需要携带用户ID,那么这个时候,我们在站点层面就可以控制一个用户ID只路由一个请求到后端中,其他请求,站点都可以抛弃,直接返回false了。这样,同一个用户不管1秒发起的10000个下单请求还是10个下单请求,只会有一个请求被放行。这样即使有些用户使用了第三方抢票软件,我们也可以控制每个用户之间的请求是公平的。

甚至我们还可以做一些恶意攻击的处理方案,例如当1s发起了1000个请求,将其用户ID放入小黑屋待一段时间(布隆过滤器),或者将这个主机ip加进去,这样的话,就又控制了一批非人为操作发起的请求。

上面说的是写请求,那么获取请求呢?返回false?那这个时候也是不合理的,我们这个时候还是需要考虑缓存,站点层面的数据缓存,例如,用户获取当前商品的库存,这个时候,我们不以用户ID作为缓存键,而是以用户请求的商品的ID为缓存键,这样,即使两个不同的用户发起的请求,我们也可以实现缓存共用了。当用户1查询火车A的票余量的时候,生成的缓存,用户2也去查询火车B的票余量的时候,当超出限额流量的时候,也返回这个缓存数据,那么真实的请求就不会直接路由到业务服务上去。这也是一种保障用户友好体验的行为了。如果我们直接抛“请求过快,请稍后再重试”,你烦吗?我挺烦的。

对于此处,我们可以考虑“七层负载均衡”,通过nginx实现。如果想提高系统的吞吐率,我们可以使用增加节点方式,增加系统的吞吐率性能。

业务应用

存在一种这样的情况,服务已用户的账户进行限流,那么这个时候,如果我用1000个账户去抢票呢?其他用户只能用自己的1个账户去抢票,那么我的抢票的成功的概率是不是相对高一些呢?那这个时候,系统的并发也会有1000,再结合真实的人为产生的并发,也是有很高的并发量,那这个时候对于系统而言,怎么控制顺序读写?

mysql官方宣称写操作,单机并发2000写操作极限。再多就爆了。

那么redis官方宣称单机并发80000写操作,那这就可以解决很多流量问题了。

然后我们需要真实的控制可控的请求到数据库层面,那么如何控制呢?也就是缓存限流。

票的余量有1000张,10000个请求如果全部请求到数据库中?后面的9000个请求都直接返回票已卖光,这样不就可以吗?可以通过缓存记录票余量,直接在缓存中操作数量的读写操作,对于缓存的数据我们采用异步入库操作。定时将票的余量同步至数据库中。这样也保证了数据的持久性。 那么怎么控制买票的有序执行呢?队列,我们可以通过有序队列,消费下单请求,这样也保护了数据库的安全性。不使用队列,直接通过一个状态进行记录当前售票的情况,当我们记录到第1100个请求后,就直接将“票是否售完”状态变为true,那么这个时候,后面的请求都直接返回“票已售光”,那么就降低了系统逻辑的处理负载。

当然,对于业务应用,我们可以通过产品规则去解决,通过一些案例去解决。

例如:分时段操作,将用户从产品设计上进行拆分,这也是一种分散流量的操作。

对于"用户取消订单"的这种操作,我们可以将缓存中的票的余量进行重建,将票的余量+1,然后再将“票是否售完”状态变为false,这个时候我们会惊奇的发现,过了1个小时了,突然发现又有票了,奇怪哈!

在双十一的时候,淘宝也做了一个操作,就是“双十一当天禁止取消订单”操作,只能通过拦截方式。这是属于产品设计上进行系统保护。

数据库

从数据库层面而言,我们只需要考虑几点:保证数据库的可用性、保证数据的持久性、保证业务数据的正确性(不能卖票卖到还剩-10张吧?)

对于数据库的特性而言,存在行锁,多条请求,我们在多个请求的时候,当一个请求在修改数据库的数据的时候,就会出现排他锁,其他操作都是阻塞的,那么我们如果解决呢?排他锁,能够保证业务的正常,事务的隔离性,数据的脏读、幻读、重复读等异常情况,显然,我们不能直接不用innodb,对于互联网项目而言,读多写少,我们还是需要考虑事务问题,那么这个时候,我们就可以对数据进行拆分了。当票的余量的表的数据过大,我们可以考虑水平分表,分库,通过地域进行拆分。用售票规则而定,假如一张“杭州东” ~ “南昌西”的车次的票,我们可以将其放在“浙江库的杭州表”中,那么杭州始发地的票的余额,我们都可以知道去哪里查询,那么对于这趟车次的用户假设也很多呢?我们怎么解决一条数据的并发写操作呢?这里我们可以考虑将始发地进行拆分。都知道,我们12306放票规则是根据始发地分配的。

“杭州东” ~ “南昌西”

会途径 “金华”/"上饶" ,那么这个时候,我们假设这趟车一共有1000张票,那么“杭州东” 可以卖500张,“金华”可以卖 300张 “上饶”可以卖200张(当然,卖火车票不是这么简单的,我们需要考虑出发地,目的地,才能知道区间的票的购买余量,并且还需要控制始发地的放票量,才能给中间的站点买票数量)。那么这样我们就可以将一个车次的票拆分为3条数据,这样,3条数据就便于我们写操作了。

对于上述的业务而言,存在不严谨的数据假设,此处也只是为了举例思考。欢迎各位举例批评。

总结:

以上为个人通过个人学习,网络大佬的分享,总结的一些思考,希望各位bu she li jiao (没打出来这个成语,尴尬了)

什么是“秒杀”?为什么传统项目中也有“秒杀”的概念?一起来分析一下.相关推荐

  1. vue项目中,接手别人代码的,如何去分析?

    首先拿到别人的代码的时候去分析以下几个事情.这里使用VUE项目举例, 一.首先观察package.json 看看是否是脚手架搭建,以及跑项目命令.分析是脚手架几 2 ? 3 ?4? npm run d ...

  2. 电商项目中的SPU和SKU概念

    SPU SPU:Standard Product Unit,标准产品单位. 概念:SPU 是商品信息聚合的最小单位[即:商品共同的属性],是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的 ...

  3. 三角传输的在链路均衡项目中的灵活应用

    首先需要解释一下三角传输的概念,该概念正常情况下适用于特定应用类型的服务器均衡项目中.为了明晰基本概念,我们先以正常环境下的数据流向示范. 常见的服务器部署方式中,最多的为旁路部署,因为该方式不需要用 ...

  4. 分析洋葱模型实现原理,在自己项目中接入洋葱模型

    分析洋葱模型实现原理,在自己项目中接入洋葱模型 上一篇文章初识洋葱模型,分析中间件执行过程,浅析koa中间件源码简单的介绍了 基于 koa 的洋葱模型的中间件的运行过程,了解了一下中间件的写法 不过基 ...

  5. 传统MVP用在项目中是真的方便还是累赘?

    原文地址: http://www.jianshu.com/p/ac51c9b88af3 qq群:301733278 前言(最后奉上福利) 自从Google在去年放出MVP的官方Sample后,越来越多 ...

  6. 预约活动(秒杀)项目中如何高效的保证下单交易成功?保证redis,mysql的最终一致性?

    预约活动(秒杀)项目中如何高效的保证下单交易成功?保证redis,mysql的最终一致性? 前言 `在秒杀项目中,秒杀下单的过程中都需要经历四步,分别为: 1.校验下单状态,商品是否存在,用户是否合法 ...

  7. 面试精讲之面试考点及大厂真题 - 分布式专栏 13项目中为什么要使用消息队列

    13项目中为什么要使用消息队列 学习从来无捷径,循序渐进登高峰. -- 高永祚 引言 上个章节把Redis夺命连环问掰扯完,面试还没有结束,消息队列同样是面试中必问的,分布式构建三把斧:缓存+异步+数 ...

  8. 如何优化传统项目,提高web应用的吞吐量

    点击上方"后端技术精选",选择"置顶公众号" 技术文章第一时间送达! 作者:赐我白日梦 cnblogs.com/ZhuChangwu/p/11872124.ht ...

  9. 电商项目中的经典问题

    转载自:https://blog.csdn.net/A_BlackMoon/article/details/80094814 请描述一下这个系统? [回答技巧] 从3个方面来回答这个问题: |--系统 ...

  10. 秒杀数字后端实现中clock gating使能端setup violation问题

    秒杀数字后端实现中clock gating使能端setup violation问题 文章右侧广告为官方硬广告,与吾爱IC社区无关,用户勿点.点击进去后出现任何损失与社区无关. 点击标题下「蓝色微信名」 ...

最新文章

  1. Maven就是这么简单
  2. powerDesiger uml class
  3. java正则hitend,Java Matcher hitEnd()用法及代码示例
  4. Intel Realsense D435 获取摄像头option参数值 get_option()
  5. MFC多标签页对话框
  6. 推荐七款精挑细选的电脑软件,欢迎收藏!
  7. 自定义SpringBoot的运行动画---美女
  8. [Chatter] 看小说「数字风暴」有感
  9. 电商管理系统源码_Dubbo/SSM/Elasticsearch/Redis/MySQL搭建分布式电商购物商城
  10. python源码中的学习笔记_第7章_字符串
  11. 高斯消去法,列主元法,LU分解法python程序
  12. 跟我一起学习VIM - vim插件合集
  13. python教你画一棵树
  14. 怎么架设魔兽世界服务器?
  15. 高斯投影正反算C语言程序代码,一个老师给的高斯投影正反算c++源码.doc
  16. C# WPF 进度条,根据读取数据显示进度条进度,根据Excel文件读取数据,进度条样式...
  17. 5分钟理解边缘概率,联合概率,条件概率,随机事件独立,随机事件依赖
  18. 企业微信生态下的会员管理系统
  19. 单片机通信总述——理论部分(CAN、串口、SPI、I2C等)
  20. 基于UDP的网络聊天室网络编程0811作业-洪庆乐

热门文章

  1. Python爬虫技术-根据【理财】关键字爬取“巨潮资讯网”的title
  2. RGB-D相机(Azure Kinect DK)RGB图、深度图的获取,配准与保存
  3. USACO 1359. 城堡(并查集)
  4. linux cpu占用分析,Linux下CPU占用率高分析方法
  5. Excel 快捷键大全
  6. 数据库笔试面试(第一版)——根据题目完成以下50道SQL语句
  7. php中下载csv文件怎么打开,php – 下载csv文件
  8. Current_Path 获取脚本所在路径(当前路径),取当前时间做文件名(uformat)
  9. N年前的实习记录 - 职场生涯应如何规划?
  10. RegShot(注册表比较工具)v2.0.1.68绿色中文版