写在前面
秒杀系统特点是瞬时流量较大,我们先看几个数据。
比如小米秒杀,三星秒杀都是瞬时抢走十几万台手机,天猫最快破亿的一个旗舰店,双十一峰值可达到60w以上的qps。后端的k-v集群峰值可达几千万qps,单机可达到30w qps,这些主要是读流量,写流量则小的多,比如对应时间点的减库存写操作也就几kqps。
搭建一个秒杀系统的架构我们可以从以下几个角度入手:
热点隔离
采用隔离方案是将秒杀系统中的热点链路隔离出来,这也是设计秒杀系统的第一原则,梳理热点数据和热点链路。
我们不希望因为1%的热点请求影响其他的99%将整个系统打垮,隔离出来之后我们可以进行后续的治理了。
秒杀系统我们可以从多个角度进行隔离:业务隔离,系统隔离,数据隔离。
业务隔离
秒杀基本属于一种营销策略,营销活动,卖家的参加活动需要通过BD报备,报名参加,经过这种报名方式我们可以知道哪些是热点业务了,包括参与秒杀活动的数据哪些是热点,我们可以提前做好预热。
系统隔离
在进行业务热点识别之后,我们可以采用分离术,将热点数据进行隔离,比如独立部署1%和99%的热点系统,针对于秒杀需求可以申请单独的域名,目的还是不让1%热点请求影响整个集群。
数据隔离
秒杀场景中大部分数据是热数据,可以启用独立的缓存集群或者mysql集群存放热点数据,目的还是隔离开,不让1%影响整体集群存储的数据问题。
通过以上三种方案我们知道整体上是进行隔离,不让热点请求热点数据影响整个系统整个集群,其他的分离方案还有很多,比如按照用户区分,不同用户分配不同的cookie,在接入层路由到不同服务接口中。入口层可以对于请求接口进行限流策略。
服务层负载调用不同的服务接口。数据层采用数据打标方式进行热点数据区分,目的是识别出热点数据和普通数据。
动静隔离
在进行了必要的隔离之后,我们接下来可以进行动静分离操作了,这个也是解决大流量系统的第二个原则。
具体可以参考一些成熟的案例,比如【高访问量系统的动态化架构设计】或开涛的京东详情页设计方案等。秒杀系统会将商品详情页独立处理进行动静分离。
这样可以把90%的静态数据缓存到客户端浏览器或cnd上,真正秒杀开始之后,点击秒杀按钮即可,而不会刷新整个页面,这样可以减少服务端响应的数据,而且大部分数据是静态化的。由于秒杀的动态数据很少,整体上性能可以提升几倍。
削峰填谷
对于防止机器秒杀造成的无效流量可以引入答题功能。
增加答题功能,时间控制到2s后,可以有效防止机器秒杀,
答题秒杀另一个功能是将瞬时秒杀流量拉长了,以前的1s进入的海量流量可以通过答题延长到几秒到10s钟,请求峰值会拉长,可以有效降低服务端压力。
秒杀请求先到先得,后面的请求自然就没有库存了,到最后的下单步骤,真正的写请求并发也就有限了。这种设计思路很普遍。
除了在客户端做文章外,服务端可以采用锁或者消息队列方式将瞬时流量拉平。
数据分层
对于大流量系统,数据分层也是重要的设计原则,通过分层可以将请求做成漏斗设计,不同层次系统可以将无效请求过滤,漏斗末端才是真正有效请求,请求经过整个漏斗之后,有效请求并发会大大降低。
漏斗一般有以下几种过滤:
大量静态不需要校验的数据放在离用户近的地方,前端系统中可以校验部分基本信息,比如用户的秒杀资格,商品状态是否正常,答题是否正确,秒杀活动是否结束等。
在请求到达服务端再进行一次校验,同时识别非法请求,判断营销价格是否符合活动要求,判断积分是否满足等,之后进行库存检查。
最后数据层保证数据的最终准确,比如库存不能减成负数。
热点发现
秒杀系统在大流量下的热点数据是一个问题,我们通过隔离方式可以在活动开始之前识别出热点数据。在活动进行时我们还可以增加一层保护,防止活动进行时流量激增造成的影响提前做好保护。
比如根据历史成交记录发现热门商品,分析购物车记录发现哪些商品好卖,通过类似方式可以动态识别出热点商品,热点数据。
对于活动进行中热点数据的发现则是比较困难,比如一些数据活动期间突然成为了热点数据,这样对我们整个系统可能会有潜在的影响。
这种情况我们需要通过实时热点数据分析,可以在3s内发现交易链路上的实时热点数据,然后根据热点数据,每个系统做好实时保护。
保护模式如下:
关键部分包括: