-->

架构实战案例解析_18_17_高性能架构案例如何设计一个秒杀系统

你好,我是王庆友。

在上一讲中呢,我和你详细介绍了打造一个高性能系统的应对策略和价格手段。

那么今天我就以一号店的秒杀系统为例,来具体说明如何实现一个高性能的系统。

那我先说一下背景,那我零一四年的时候,一号店作为网上超市类电商,经常在线上举行各种大促活动。

比如说进口牛奶促销活动,每次促销的牛奶呢有几十万盒促销,价格非常优惠。

一般这样的促销活动会在某个整点的时间进行开卖。

比如说上午十点,那对于这种至高价优并且是刚需的商品,会有大量的用户来抢购。

那俗话说手快有手慢无,往往短短几分钟内所有牛奶就能售卖完毕。

那我们可以看到这本质上是一种秒杀活动,但它的商品数量非常大,一瞬间呢会有大量的用户流量涌进来,流量可以高达平时的几十倍,而且和少量商品的秒杀不同,这些呢都是有效流量,最终会生成实际的订单。

而在正常的情况下,系统因为资源有限,只能处理百分之十的流量,那无法处理剩下的百分之九十流量。

这个瞬间高并发的流量涌入,很大程度上会引起后台系统超时报错,导致前台用户下单不成功。

那这样一来呢,用户就会反复刷新页面,多次尝试下单,所对活户体验不好,而且系统压力会更大。

而最终的结果呢,系统往往由于过载整体处理能力下降甚至瘫痪,导致所有用户都无法购买。

在文稿中呢我放一张图,可以直观的说明系统面临的困境。

那在这种情况下呢,对于用户来说,能不能买到商品,拼的是体力和人品。

那由于体验不好,用户会逐渐对活动失去兴趣,而对系统来说呢,我们需要拼命的加机器来满足这个分值的流量。

那每次一号店要进行大促的时候,所以活动开始前运营和技术人员呢会坐在一起大家一起的评估活动的峰值流量。

然后技术人员会做评估系统的,哪些节点需要加机器器,以及要加多少机器。

但这样做法呢其实存在几个问题。

首先我们对峰值流量的预估以及要加多少机器都是拍脑袋的,和实际出入呢往往很大,一旦估计少了系统,同样会面临过载的风险。

其次呢,为了短暂的几分钟促销,我们需要增加大量的机器,而且事先要做很多的运维准备工作,不但浪费资源,而且效率很低。

最为关键的是,有些处理节点系统不是通过加机器就能扩展处理能力的。

比如说商品的库存数据库下单的时候,我们需要对它进行扣库存啊,为了防止库存更新冲突,我们需要锁定库存记录,导致系统的并发处理能力非常有限。

那这个呢靠纯粹的加机器是解决不了的那对于这种高并发情况看来,让系统单纯的通过加机器去硬扛是不行的。

那么我们有没有更好的办法既能保证用户体验,又能保证系统能够轻松的应对这种流量挑战呢?我们现在深入的分析下这个业务场景。

这个秒杀活动的特点呢是在短期的一到两分钟内这个流量场景。

那只要促销的商品卖完流量马上恢复常态。

所以说对前端短期内这么大的下单请求,后端如果实时去处理,压力会非常的大。

但如果我们把这个处理时间延长到十分钟,那后端呢他是可以完成下单的那对用户来说,商品的优惠力度这么大,他们比较关心的是是否能够买得到。

所以呢他们愿意多等一段时间,而不是在页面上一次次的点击下单。

然后呢每次系统都提示他下单失败。

当然,如果我们把订单处理时间延长了,只要我们在前端告诉用户,系统已经接受了他们的订单,并且不断同步用户后台订单处理的进度。

这样对用户体验来说呢,问题也不是很大。

那基于这个分析,我们就可以利用异步处理的思路来应对秒杀活动。

那具体的做法是,我们先在前端接收用户所有的下单请求,但不在后端实时生成订单,而是把它放在队列里面。

然后系统根据后端订单中心的实际处理能力,从队列里获取订单请求,再交给订单中心生成实际的订单。

那同时呢系统会告诉用户当前的处理进度有多少,订单排在他的前面,他还要等待多久。

那这样对用户来说呢,他在前台下单一次就可以了,然后呢就可以等系统慢慢处理,这也符合先到先得的原则啊,非常公平合理。

那对系统来说呢,只要根据大促的商品总量,我们一一定程度上增加系统的处理能力。

要保证下单请求,从进来到最后处理,完成这个时间相对合理就可以了。

那举个例子,比如说商品数量有二十万,那每人限购一件。

这样呢我们预计用户会在两分钟内完成下单,但用户他能够接受系统在二十分钟内完成这个订单处理。

那这样子呢,系统只要保证每分钟能处理一万订单就可以了啊,如果不采取这种排队的方式,系统就需要每分钟实时处理十万订单,那它的压力呢就会提升一个数量级。

所以基于这个排队的思路,我们设计了系统的总体架构,你可以去文稿中看一下。

在这个架构中呢,我们在前台和后台下单系统之间新增加了一个排队系统,它包含排队区和处理区两个部分系统整理的处理过程是这样子的。

首先呢,用户在商品详情页提交订单后,这个订单会作为预订单进入排队区,同时排队系统会返回用户一个排队编号。

这个订号用于跟踪后续的订单处理进度。

然后呢,用户会被引导到一个等队区。

这个页面呢会根据前面的排队号定时的查询排队系统,排队系统会返回这个预订单在队列中的位置信息,包括他前面还有多少未处理的预订单以及后台系统,大概还要后久会处理这个预订单,这样用户就不会焦虑。

系在排队系统的处理区。

我们有很多的消费者,包们会依次从排队区的队列里获取预订单,然后调用后台下单,系统生成实际的订单。

那随着这个预订单变成正式的订单,队列的预订单会逐渐变少。

那如果当前的预订单已经从队列里被移除了,那用户的等待页呢就会检测到这个情况,页面会自动跳转到订单的完成页。

那接下来呢就和常规的购物流程一样了,用户进行最后的支付,最终完成整个前台下单过程。

那这里呢你可以看到前台的预订单,有顺时的大流量。

那我们呢只是把它放在队列里面,这个处理起来很快,排队系统可以轻松的应对。

那后台生成实际订订单它是匀速的,并且最大化的发挥了下单系统的处理能力。

那另外方面呢,对于用户体验来说,用户他可以选择在等待页等候实时的获取订单处理进度的反馈。

它也可以选择离开,然后在用户中心的待支付订单里面完成支付。

那通过这样的设计,排队系统,竟保证了系统处理订单的能力,那保证了用户良好的体验。

那我在文稿中呢也放了一张等待页的效果图,你可以去看一下,直观的了解秒杀系统的用户体验。

好,现在你已经了解了秒杀系统的总体设计。

那接下来呢我深入介绍一下这个排队系统的内部设计细节,帮助你更好的理解它。

那首先我们针对队列的技术选型,排队系统使用的是REDIS,而不是MQ.因为相对于MQ来说,REDS它更加轻亮级,性能更好。

它内置的队列的数据结构,那除了跟MQ一样,是消息的先进先出以外,我们还可以获取队列的长度,以及通过队队号获取消息队队列的位置置样,我们就可以给前端反馈预订单的处理进度。

那对于秒杀场景来说呢,一个订单只能包含一个商品。

这里我们为每个秒杀商品提供一个单独的队列,这样呢就可以分散数据在redi s中的存取。

那多个队列它可以提供更好的性能。

那关于队列的调度问题,也就是消费者优先,从哪个队列拿预订单。

那排列系统会结合下单时间和队列长度来确定,以保证用户合理的时间体验。

比如说某个秒杀商品的队列很长,那消费者呢会优先从这个队列拿预订单,从而避免用户等待太长的时间。

那关于队列长度,为了保证用户能够买到数量,我们并不是把所有前台下单请求都会放到队列里,而是根据参与活动的秒杀商品数量,按照一比一的比例,设置队列的初始长度,这样保证进入队列的请求,最终都能生成订单。

比如说可用队列长度呢,它随着预订单进入队列不断的减少。

那当数字为零零时候候,单单内会拒绝接受新,请请进入队列列,直接返回,户户,单单失败。

那当如如果后订订单生成异常,或用户户取订订单后,可用队列长度会增加,这个会重新开新队列列入队列。

那系统除了秒杀流程,还有常规的购物流程。

这两个购物流程呢都是从详情页开始,到订单完成页结束。

那不同的地方在于呢常规购物流程走的是购物车加结算页,那系统它是同步处理的,这样呢也可以有更好的用户体验。

那在这里呢我们在系统设计的时候,可以很好的同时支持秒杀流程和常规购物流程。

如果运营人员在后台上架商品的时候设置,这是一个秒杀商品。

那么从详情页开始,系统就会引导用户走秒杀流程,否则呢就走常规的购物流程。

那特别是在早期我们秒杀系统刚刚落地的时候,如果发现秒杀流程有问题,我们还可以快速的切回到常规的购物流程,实现一定程度上的系统互备。

那还有对于秒杀活动来说,参与活动的商品种类它是有限的,但这些商品库存的扣减非常频繁。

因此,我们建立了活动库存的概念,把少量参与促销的商品种类单独放在一个库里面,避免和大量常规的商品放一起,这样也大幅度提高了库存数据库的读写性能。

那好了,通过这个秒杀系统的架构设计,你可以看到我们巧妙的通过请求的异步化处理,对流量进行消分,从而保证了系统的高性能。

这里呢我们不需要增加太多的机器。

在系统落地的时候,我们通过排队系统对前后台解耦后台下单,系统基本上也不需要修改系统,整体改造的工作量不大。

整个落地过程呢也非常顺利啊。

不过值得注意的是,这种方式它比较适合顺时,有高并发流量。

比如这里说的秒杀场景。

那如果订单的高峰会持续一段较长的时间啊,用户对订单处理又有比较高的时间要求,那么就不适合采用这种异步消分的方式。

那举个例子来说,外卖订单的午高峰通常会持续两个小时。

那用户普遍期待订单半个小时能够送达。

那对于这种情况,我们就需要正面应对高峰流量。

比如通过水平扩展各个节点提升系统的处理能力。

这呢也要求系统能够做到弹性伸缩,高效的支持资源的缩容和扩容,节省成本。

那最后我总结一下今天所讲的内容。

那么我针对药店的大促业务挑战和你分享了一个秒杀系统的具体设计。

那对照我在上一家中介绍的高性能应对策略,秒杀系统呢主要使用了异步化处理的方式,这也符合实际的业务场景。

那通过今天的分享,相信你要如何保障系统的高性能有了更深入体会。

如果你也有类似的顺势高并发的场景,你也可以考虑在实践中参考这里的做法。

那最后给你留一道思考题,你的公司业务上有高发发场景景系统,它是如何应对的呢?欢迎给我留言,我会及时给你反馈。

如果你觉得有收获,也欢迎把这篇文章分享给你的朋友,感谢收听,我们下一期再见。