吊打面试官——秒杀系统设计

首先设计一个系统以前,咱们须要先确认咱们的业务场景是怎么样子的,我就带着你们一块儿假设一个场景好吧。前端

场景程序员

咱们如今要卖100件下面这个婴儿纸尿裤,而后咱们根据以往这样秒杀活动的数据经验来看,目测来抢这100件纸尿裤的人足足有10万人。(南极人打钱!)web

秒杀系统设计:吊打面试官

 

你一听,完了呀,这咱们的服务器哪里顶得住啊!说真的直接打DB确定挂。可是别急嘛,有暖男敖丙在,咱们在开始以前应该先思考下会出现哪些问题面试

问题算法

高并发:数据库

是的高并发这个是咱们想都不用想的一个点,一瞬间这么多人进来这不是高并发何时是呢?后端

是吧,秒杀的特色就是这样时间极短、 瞬间用户量大缓存

正常的店铺营销都是用极低的价格配合上短信、APP的精准推送,吸引特别多的用户来参与这场秒杀,爽了商家苦了开发呀服务器

秒杀你们都知道若是真的营销到位,价格诱人,几十万的流量我以为彻底不是问题,那单机的Redis我感受3-4W的QPS仍是能顶得住的,可是再高了就没办法了,那这个数据随便搞个热销商品的秒杀可能都不止了。网络

大量的请求进来,咱们须要考虑的点就不少了,缓存雪崩缓存击穿缓存穿透这些我以前提到的点都是有可能发生的,出现问题打挂DB那就很难受了,活动失败用户体验差,活动人气没了,最后背锅的仍是开发

秒杀系统设计:吊打面试官

 

超卖:

但凡是个秒杀,都怕超卖,我这里举例的只是尿不湿,要是换成100个华为MatePro30,商家的预算经费卖100个能够赚点还能够造势,结果你写错程序多卖出去200个,你不发货用户投诉你,平台封你店,你发货就血亏,你怎么办?

那最后只能杀个开发祭天解气了,秒杀的价格原本就低了,基本上都是不怎么赚钱的,超卖了就恐怖了呀,因此超卖也是很关键的一个点。

秒杀系统设计:吊打面试官

 

恶意请求:

你这么低的价格,假如我抢到了,我转手卖掉我不是血赚?就算我不卖我也不亏啊,那用户知道,你知道,别的别有用心的人(黑客、黄牛…)确定也知道的。

那简单啊,我知道你何时抢,我搞个几十台机器搞点脚本,我也模拟出来十几万我的左右的请求,那我是否是意味着我基本上有80%的成功率了。

真实状况可能远远不止,由于机器请求的速度比人的手速每每快太多了。

Tip:科普下,小道消息了解到的,黄牛的抢票系统,比国内不少小公司的系统还吊不少,架构设计都是顶级的,我用顶配的服务加上顶配的架构设计,你还想看演唱会?还想回家?

不过不用黄牛我回家都难,咱们云贵川跟我同样要回家过年的仔太多了555!

连接暴露:

前面几个问题你们可能都很好理解,一看到这个有的小伙伴可能会比较疑惑,啥是连接暴露呀?

秒杀系统设计:吊打面试官

 

相信是个开发同窗都对这个画面一点都不陌生吧,懂点行的仔均可以打开谷歌的开发者模式,而后看看你的网页代码,有的就有URL,可是我写VUE的时候是事件触发而后去调用文件里面的接口看源码看不到,可是我能够点击一下查看你的请求地址啊,不过你好像能够对按钮在秒杀前置灰。

无论怎么样子都有危险,撇开外面的全部的东西你都挡住了,你卖这个东西实在便宜得过度,有诱惑力,你能保证开发不动心?开发知道地址,在秒杀的时候本身提早请求。。。(开发:怎么TM又是我)

秒杀系统设计:吊打面试官

 

数据库:

每秒上万甚至十几万的QPS(每秒请求数)直接打到数据库,基本上都要把库打挂掉,并且你服务不仅仅是作秒杀的还涉及其余的业务,你没作降级、限流、熔断啥的,别的一块儿挂,小公司的话可能全站崩溃404

反正无论你秒杀怎么挂,你别把别的搞挂了对吧,搞挂了就不是杀一个程序员能搞定的。

程序员:我TM好难啊!

问题都列出来了,那怎么设计,怎么解决这些问题就是接下去要考虑的了,咱们对症下药。

服务单一职责:

设计个能抗住高并发的系统,我以为仍是得单一职责

什么意思呢,你们都知道如今设计都是微服务的设计思想,而后再用分布式的部署方式

也就是咱们下单是有个订单服务,用户登陆管理等有个用户服务等等,那为啥咱们不给秒杀也开个服务,咱们把秒杀的代码业务逻辑放一块儿。

单独给他创建一个数据库,如今的互联网架构部署都是分库的,同样的就是订单服务对应订单库,秒杀咱们也给他创建本身的秒杀库。

至于表就看你们怎么设计了,该设置索引的地方仍是要设置索引的,建完后记得用explain看看SQL的执行计划。(不了解的小伙伴也没事,MySQL章节我会说的)

单一职责的好处就是就算秒杀没抗住,秒杀库崩了,服务挂了,也不会影响到其余的服务。(强行高可用)

秒杀连接加盐:

咱们上面说了连接要是提早暴露出去可能有人直接访问url就提早秒杀了,那又有小伙伴要说了我作个时间的校验就行了呀,那我告诉你,知道连接的地址比起页面人工点击的仍是有很大优点

我知道url了,那我经过程序不断获取最新的北京时间,能够达到毫秒级别的,我就在00毫秒的时候请求,我敢说绝对比你人工点的成功率大太多了,并且我能够一毫秒发送N次请求,搞很差你卖100个产品我全拿了。

秒杀系统设计:吊打面试官

 

那这种状况怎么避免?

简单,把URL动态化,就连写代码的人都不知道,你就经过MD5之类的加密算法加密随机的字符串去作url,而后经过前端代码获取url后台校验才能经过。

暖男我呢,又准备了一个简单的url加密给你们尝尝鲜,还不点个赞

秒杀系统设计:吊打面试官

 

Redis集群:

以前不是说单机的Redis顶不住嘛,那简单多找几个兄弟啊,秒杀原本就是读多写少,那大家是否是瞬间想起来我以前跟大家提到过的,Redis集群主从同步读写分离,咱们还搞点哨兵,开启持久化直接无敌高可用!

秒杀系统设计:吊打面试官

 

Nginx:

Nginx你们想必都不陌生了吧,这玩意是高性能的web服务器,并发也随便顶几万不是梦,可是咱们的Tomcat只能顶几百的并发呀,那简单呀负载均衡嘛,一台服务几百,那就多搞点,在秒杀的时候多租点流量机

Tip:据我所知国内某大厂就是在去年春节活动期间租光了亚洲全部的服务器,小公司也很喜欢在双十一期间买流量机来顶住压力。

秒杀系统设计:吊打面试官

 

这样一对比是否是以为你的集群能顶不少了。

恶意请求拦截也须要用到它,通常单个用户请求次数太夸张,不像人为的请求在网关那一层就得拦截掉了,否则请求多了他抢不抢获得是一回事,服务器压力上去了,可能占用网络带宽或者把服务器打崩、缓存击穿等等。

资源静态化:

秒杀通常都是特定的商品还有页面模板,如今通常都是先后端分离的,因此页面通常都是不会通过后端的,可是前端也要本身的服务器啊,那就把能提早放入cdn服务器的东西都放进去,反正把全部能提高效率的步骤都作一下,减小真正秒杀时候服务器的压力。

按钮控制:

你们有没有发现没到秒杀前,通常按钮都是置灰的,只有时间到了,才能点击。

这是由于怕你们在时间快到的最后几秒秒疯狂请求服务器,而后还没到秒杀的时候基本上服务器就挂了。

这个时候就须要前端的配合,定时去请求你的后端服务器,获取最新的北京时间,到时间点再给按钮可用状态。

按钮能够点击以后也得给他置灰几秒,否则他同样在开始以后一直点的。你敢说大家秒杀的时候不是这样的?

秒杀系统设计:吊打面试官

 

限流:

限流这里我以为应该分为前端限流后端限流

前端限流:这个很简单,通常秒杀不会让你一直点的,通常都是点击一下或者两下而后几秒以后才能够继续点击,这也是保护服务器的一种手段。

后端限流:秒杀的时候确定是涉及到后续的订单生成和支付等操做,可是都只是成功的幸运儿才会走到那一步,那一旦100个产品卖光了,return了一个false,前端直接秒杀结束,而后你后端也关闭后续无效请求的介入了。

Tip:真正的限流还会有限流组件的加入例如:阿里的Sentinel、Hystrix等。我这里就不展开了,就说一下物理的限流。

库存预热:

秒杀的本质,就是对库存的抢夺,每一个秒杀的用户来你都去数据库查询库存校验库存,而后扣减库存,撇开性能因素,你不以为这样好繁琐,对业务开发人员都不友好,并且数据库顶不住啊。

开发:你tm总算为我着想一次了。

秒杀系统设计:吊打面试官

 

那怎么办?

咱们都知道数据库顶不住可是他的兄弟非关系型的数据库Redis能顶啊!

那不简单了,咱们要开始秒杀前你经过定时任务或者运维同窗提早把商品的库存加载到Redis中去,让整个流程都在Redis里面去作,而后等秒杀结束了,再异步的去修改库存就行了。

可是用了Redis就有一个问题了,咱们上面说了咱们采用主从,就是咱们会去读取库存而后再判断而后有库存才去减库存,正常状况没问题,可是高并发的状况问题就很大了。

多品几遍!!!就好比如今库存只剩下1个了,咱们高并发嘛,4个服务器一块儿查询了发现都是还有1个,那你们都以为是本身抢到了,就都去扣库存,那结果就变成了-3,是的只有一个是真的抢到了,别的都是超卖的。咋办?

Lua:

Lua 脚本功能是 Reids在 2.6 版本的最大亮点, 经过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点, 而且能够经过组合使用多个命令, 轻松实现之前很难实现或者不能高效实现的模式。

Lua脚本是相似Redis事务,有必定的原子性,不会被其余命令插队,能够完成一些Redis事务性的操做。这点是关键。

知道原理了,咱们就写一个脚本把判断库存扣减库存的操做都写在一个脚本丢给Redis去作,那到0了后面的都Return False了是吧,一个失败了你修改一个开关,直接挡住全部的请求,而后再作后面的事情嘛。

限流&降级&熔断&隔离:

这个为啥要作呢,不怕一万就怕万一,万一你真的顶不住了,限流,顶不住就挡一部分出去可是不能说不行,降级,降级了仍是被打挂了,熔断,至少不要影响别的系统,隔离,你自己就独立的,可是你会调用其余的系统嘛,你快不行了你别拖累兄弟们啊。

秒杀系统设计:吊打面试官

 

削峰填谷:

一说到这个名词,不少小伙伴就知道了,对的MQ,你买东西少了你直接100个请求改库我以为没问题,可是万一秒杀一万个,10万个呢?服务器挂了,程序员又要背锅的

Tip:可能小伙伴说咱们业务达不到这个量级,不必。可是我想说咱们写代码,就不该该写出有逻辑漏洞的代码,至少之后公司体量上去了,别人一看竟然不用改代码,一看代码做者是敖丙?有点东西!

你能够把它放消息队列,而后一点点消费去改库存就行了嘛,不过单个商品其实一次修改就够了,我这里说的是某个点多个商品一块儿秒杀的场景,像极了双十一零点。

总结

到这里我想我已经基本上把该考虑的点还有对应的解决方案也都说了一下,不知道还有没有没考虑到的,可是就算没考虑到我想我这个设计,应该也能撑住一个完整的秒杀流程。

相关文章
相关标签/搜索