如何设计一个秒杀系统

https://www.jianshu.com/p/d789ea15d060

 

之前一直准备写一篇关于秒杀系统设计的文章,但是因为涉及到的东西还是挺多的,拖延症发作一直没抽空写,最近闲了就把这个坑给填上,本文写的方案是之前在电商公司工作的时候使用的大促秒杀方案。其实秒杀系统不单单适用于电商的抢购场景,其实一切涉及到大并发的场景都适合于使用该套秒杀系统方案,例如互金系统中的抢加息券什么的也可以使用,整个方案中使用到的技术也是日常工作中经常用到的技术。

秒杀系统的难点

首先我们先看下秒杀场景的难点到底在哪?在秒杀场景中最大的问题在于容易产生大并发请求、产生超卖现象和性能问题,下面我们分别分析下下面这三个问题:

1)瞬时大并发:一提到秒杀系统给人最深刻的印象是超大的瞬时并发,这时你可以联想到小米手机的抢购场景,在小米手机抢购的场景一般都会有10w+的用户同时访问一个商品页面去抢购手机,这就是一个典型的瞬时大并发,如果系统没有经过限流或者熔断处理,那么系统瞬间就会崩掉,就好像被DDos攻击一样;

2)超卖:秒杀除了大并发这样的难点,还有一个所有电商都会遇到的痛,那就是超卖,电商搞大促最怕什么?最怕的就是超卖,产生超卖了以后会影响到用户体验,会导致订单系统、库存系统、供应链等等,产生的问题是一系列的连锁反应,所以电商都不希望超卖发生,但是在大并发的场景最容易发生的就是超卖,不同线程读取到的当前库存数据可能下个毫秒就被其他线程修改了,如果没有一定的锁库存机制那么库存数据必然出错,都不用上万并发,几十并发就可以导致商品超卖;

3)性能:当遇到大并发和超卖问题后,必然会引出另一个问题,那就是性能问题,如何保证在大并发请求下,系统能够有好的性能,让用户能够有更好的体验,不然每个用户都等几十秒才能知道结果,那体验必然是很糟糕的;

秒杀系统方案

对于上面提到的秒杀的问题,我们当时的架构是下面这样的:

Screenshot 2018-05-24 14.58.41

从整个秒杀系统的架构其实和一般的互联网系统架构本身没有太多的不同,核心理念还是通过缓存、异步、限流来保证系统的高并发和高可用。下面从一笔秒杀交易的流程来描述下秒杀系统架构设计的要点:

1)对于大促时候的秒杀活动,一般运营会配置静态的活动页面,配置静态活动页面主要有两个目的一方面是为了便于在各种社交媒体分发,另一方面是因为秒杀活动页的流量是大促期间最大的,通过配置成静态页面可以将页面发布在公有云上动态的横向扩展;

2)将秒杀活动的静态页面提前刷新到CDN节点,通过CDN节点的页面缓存来缓解访问压力和公司网络带宽,CDN上缓存js、css和图片;

3)将活动H5页面部署在公有云的web server上,使用公有云最大的好处就是能够根据活动的火爆程度动态扩容而且成本较低,同时将访问压力隔离在公司系统外部;

4)在提供真正商品秒杀业务功能的app server上,需要进行交易限流、熔断控制,防止因为秒杀交易影响到其他正常服务的提供,我们在限流和熔断方面使用了hystrix,在核心交易的controller层通过hystrix进行交易并发限流控制,当交易流量超出我们设定的限流最大值时,会对新交易进行熔断处理固定返回静态失败报文。

5)服务降级处理,除了上面讲到的限流和熔断控制,我们还设定了降级开关,对于首页、购物车、订单查询、大数据等功能都会进行一定程度的服务降级,例如我们会对首页原先动态生成的大数据页面布局降级为所有人看到的是一样的页面、购物车也会降级为不在一级页面的tabbar上的购物车图标上显示商品数量、历史订单的查询也会提供时间周期较短的查询、大数据商品推荐也会提供一样的商品推荐,通过这样的降级处理能够很好的保证各个系统在大促期间能够正常的提供最基本的服务,保证用户能够正常下单完成付款。

6)上面介绍的都是如何保证能扛住高并发,下面介绍下整个方案中如何防止超卖现象的发生,我们日常的下单过程中防止超卖一般是通过在数据库上实施乐观锁来完成,使用乐观锁虽然比for update这种悲观锁方式性能要好很多,但是还是无法满足秒杀的上万并发需求,我们的方案其实也很简单实时库存的扣减在缓存中进行,异步扣减数据库中的库存,保证缓存中和数据库中库存的最终一致性。

在这个方案中我们使用的分布式缓存是redis,使用了codis集群方案稳定性和高可用方面还是比较有保证的,因为redis是单线程写,所以也不用担心线程安全的问题,redis自身就能够保证数据的强一致性,在下单的事务中包含了实时扣减缓存中的库存和异步发送队列,由队列处理器再异步从队列中取出订单根据订单信息扣减库存系统数据库中的商品数量。

总结

整个秒杀方案就介绍这么多,其实整个的思路还是比较简单的,也没有特别复杂的地方,对于大部分公司的高并发场景还是适用的,并且比较容易实施上线,该方案对于我们当时每秒几万的并发场景是能够扛住的,但是对于像小米、12306这些在高峰时动不动几十万用户并发的场景,使用这样的方案可能用户体验方面和系统服务方面就会存在一些问题了,对于每秒几十万并发的场景我们一般除了会在技术层面进行优化,更多的会通过其他一些业务手段来进行交易分流来分散整体的高并发访问,秒杀方案就介绍到这里,具体的实现这里就不写了,我相信跟着上面介绍的思路很容易就能将代码写出来。



作者:monkey01
链接:https://www.jianshu.com/p/d789ea15d060
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

 

https://yq.aliyun.com/articles/618443

前言
最近在部门内部分享了原来在电商业务做秒杀活动的整体思路,大家对这次分享反馈还不错,所以我就简单整理了一下,分享给大家参考参考。

业务介绍

image


什么是秒杀?通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动。

比如说京东秒杀,就是一种定时定量秒杀,在规定的时间内,无论商品是否秒杀完毕,该场次的秒杀活动都会结束。这种秒杀,对时间不是特别严格,只要下手快点,秒中的概率还是比较大的。

淘宝以前就做过一元抢购,一般都是限量 1 件商品,同时价格低到「令人发齿」,这种秒杀一般都在开始时间 1 到 3 秒内就已经抢光了,参与这个秒杀一般都是看运气的,不必太强求。

业务特点

image

瞬时并发量大
秒杀时会有大量用户在同一时间进行抢购,瞬时并发访问量突增 10 倍,甚至 100 倍以上都有。

库存量少
一般秒杀活动商品量很少,这就导致了只有极少量用户能成功购买到。

业务简单
流程比较简单,一般都是下订单、扣库存、支付订单。

技术难点

image

现有业务的冲击
秒杀是营销活动中的一种,如果和其他营销活动应用部署在同一服务器上,肯定会对现有其他活动造成冲击,极端情况下可能导致整个电商系统服务宕机。

直接下订单
下单页面是一个正常的 URL 地址,需要控制在秒杀开始前,不能下订单,只能浏览对应活动商品的信息。简单来说,需要 Disable 订单按钮。

页面流量突增
秒杀活动开始前后,会有很多用户请求对应商品页面,会造成后台服务器的流量突增,同时对应的网络带宽增加,需要控制商品页面的流量不会对后台服务器、DB、Redis 等组件的造成过大的压力。

架构设计思想

image

限流
由于活动库存量一般都是很少,对应的只有少部分用户才能秒杀成功。所以我们需要限制大部分用户流量,只准少量用户流量进入后端服务器。

削峰
秒杀开始的那一瞬间,会有大量用户冲击进来,所以在开始时候会有一个瞬间流量峰值。如何把瞬间的流量峰值变得更平缓,是能否成功设计好秒杀系统的关键因素。实现流量削峰填谷,一般的采用缓存和 MQ 中间件来解决。

异步
秒杀其实可以当做高并发系统来处理,在这个时候,可以考虑从业务上做兼容,将同步的业务,设计成异步处理的任务,提高网站的整体可用性。

缓存
秒杀系统的瓶颈主要体现在下订单、扣减库存流程中。在这些流程中主要用到 OLTP 的数据库,类似 MySQL、SQLServer、Oracle。由于数据库底层采用 B+ 树的储存结构,对应我们随机写入与读取的效率,相对较低。如果我们把部分业务逻辑迁移到内存的缓存或者 Redis 中,会极大的提高并发效率。

整体架构

image

客户端优化
客户端优化主要有两个问题:

秒杀页面
秒杀活动开始前,其实就有很多用户访问该页面了。如果这个页面的一些资源,比如 CSS、JS、图片、商品详情等,都访问后端服务器,甚至 DB 的话,服务肯定会出现不可用的情况。所以一般我们会把这个页面整体进行静态化,并将页面静态化之后的页面分发到 CDN 边缘节点上,起到压力分散的作用。

防止提前下单
防止提前下单主要是在静态化页面中加入一个 JS 文件引用,该 JS 文件包含活动是否开始的标记以及开始时的动态下单页面的 URL 参数。同时,这个 JS 文件是不会被 CDN 系统缓存的,会一直请求后端服务的,所以这个 JS 文件一定要很小。当活动快开始的时候(比如提前),通过后台接口修改这个 JS 文件使之生效。

API 接入层优化
客户端优化,对于不是搞计算机方面的用户还是可以防止住的。但是稍有一定网络基础的用户就起不到作用了,因此服务端也需要加些对应控制,不能信任客户端的任何操作。一般控制分为 2 大类:

限制用户维度访问频率
针对同一个用户( Userid 维度),做页面级别缓存,单元时间内的请求,统一走缓存,返回同一个页面。

限制商品维度访问频率
大量请求同时间段查询同一个商品时,可以做页面级别缓存,不管下回是谁来访问,只要是这个页面就直接返回。

SOA 服务层优化
上面两层只能限制异常用户访问,如果秒杀活动运营的比较好,很多用户都参加了,就会造成系统压力过大甚至宕机,因此需要后端流量控制。

对于后端系统的控制可以通过消息队列、异步处理、提高并发等方式解决。对于超过系统水位线的请求,直接采取 「Fail-Fast」原则,拒绝掉。

秒杀整体流程图

image

秒杀系统核心在于层层过滤,逐渐递减瞬时访问压力,减少最终对数据库的冲击。通过上面流程图就会发现压力最大的地方在哪里?

MQ 排队服务,只要 MQ 排队服务顶住,后面下订单与扣减库存的压力都是自己能控制的,根据数据库的压力,可以定制化创建订单消费者的数量,避免出现消费者数据量过多,导致数据库压力过大或者直接宕机。

库存服务专门为秒杀的商品提供库存管理,实现提前锁定库存,避免超卖的现象。同时,通过超时处理任务发现已抢到商品,但未付款的订单,并在规定付款时间后,处理这些订单,将恢复订单商品对应的库存量。

总结
核心思想:层层过滤
尽量将请求拦截在上游,降低下游的压力
充分利用缓存与消息队列,提高请求处理速度以及削峰填谷的作用

参考
秒杀业务架构优化之路
http://www.infoq.com/cn/articles/flash-deal-architecture-optimization
互联网秒杀业务设计
https://baijia.baidu.com/s?old_id=108134
高并发秒杀系统架构设计
https://zhuanlan.zhihu.com/p/25368538

原文发布时间为:2018-07-21
本文作者:曹林华
本文来自云栖社区合作伙伴“全栈开发者社区”,了解相关信息可以关注“全栈开发者社区”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值