文档章节

互联网秒杀业务架构设计

陶邦仁
 陶邦仁
发布于 2015/11/11 10:52
字数 2641
阅读 1234
收藏 15

#0 系列目录#

#1 抢购业务介绍# 我们常见的抢购业务分两种: 限时抢购、限量抢购,我简单分析了下这些case,如下图:

输入图片说明

输入图片说明

想必小米的抢购运营的最火爆了,每发一款新品,都限量发售,每次搞的大家心里痒痒的。记得之前还因为抢购太火爆,站点打不开,崩溃了。那么问题来了:为什么抢购总是引发RD、OP恐慌?我理解是,爆品太火爆,瞬时请求太大,导致业务机器、存储机器都在抢购高峰时扛了太多压力。那么,我们今天以一个抢购业务场景为例,看看如何扛住压力,做好抢购业务!假设,这时候我们接到了产品层面的需求,如下图:

输入图片说明

#2 抢购项目设计# 通过我们先行的抢购需求分析,我们画一个粗略的流程图,如下:

输入图片说明

我们将自身简单划为两部分:业务层、数据层,并且旁路设计一个“运营控制”环节。当然,数据源自第三方嘛,我们的数据层基于第三方资源数据构建。

这时,我们来看看这个草图里几个库和几个数据流,是怎样的。

首先,看看库。

数据层的“商品库”,显而易见,用于存储第三方商品数据,通过第三方推、我们拉的方式来构建这个数据库信息。

数据库层的“抢购计划”库,主要由旁路的“运营控制”环节产生的数据,由运营同学来维护抢购场次、商品数量。

业务层的“抢购库”,其实是商品库的子集,由运营同学勾选商品并配好该商品放出多少用于抢购,发布到业务层面的抢购库中。

业务层的Transaction Data,一会我们讲到与第三方对账时候,我们再说它。

##2.1 如何解耦前后端压力##

  1. 让我们业务的压力,不会传递到资源方,避免造成资源方接口压力同比增长。所以,我们自己建了商品库,此时,第三方笑了。

  2. 业务层与数据层解耦,我们让抢购库位于业务层,让商品库位于数据层。因为我们可以想象到,抢购高峰来临时,查询“商品还有没有?”的请求是最多的,若“有没有”这种高频请求每次都去数据层,那我们其实就将业务、数据耦合在一起了,那么,就有了抢购库这个子库,在业务层抗压力。(这里可以明确的是,数据层的商品库为关系型存储,业务层的抢购库为nosql的)。

有了业务层的nosql(我们就用redis吧)抗高频压力,数据层的商品库笑了。

这里就可以抛一个思想了:我们的架构设计中,需要分解压力,在互联网项目中,来自于用户的大流量不少见,这些流量最终都会落到一个地方,就看我们的设计如何分解这个压力了,如何避免它层层传递。抛个case,我们的水平分布业务机器,也是考虑通过水平扩展实例的方式,来分解大流量压力。

不扯概念的东西了,我们回归我们的抢购业务。

有了简单的分层设计,解决的大家都担心的压力问题,我们就看看抢购业务的时序是怎样的。 我们的时序图分两个视角来说明:

  1. 商品的角度:

**商品角度的时序图,从左到右:资源方、数据层、旁路-运营控制层、业务层。如下图: **

输入图片说明

录入商品即商品从资源方发布到我们的数据层,形式可以是通过API、可以是通过文件传输、可以是我们去拉去。通过我们的代码逻辑,记录到我们数据层的“商品库DB”。

有了自建的商品库的数据,我们的运营同学就可以基于商品库设计每天的抢购场次(此事就有Web界面的事情,这里我们就不展开这块了),运营同学创建好一批抢购场次,记录在数据层的“抢购计划”这一关系型数据库中

运营同学创建完抢购场次后,没完事,还得应产品需求,基于商品库,配置每场抢购场次中覆盖的商品,及商品的数量。这些抢购场次内的商品配置,会简单的记录在业务层的“抢购库”中。(抢购库记录的信息较为简单,例如商品库中ID为123123的商品有100件,业务层的抢购库中只存ID 123123商品运营配了在第X场抢购中有5件)。

此时,数据层的商品库有了资源方数据、数据层的抢购计划库中有运营配的抢购计划,业务层的抢购库中每场抢购活动中商品的情况。

那么,业务层此时就可以基于时间,来展示运营配的抢购场次了。业务层,如何展示,这块就是拼装数据、前端效果了,这里也不展开了。

  1. 用户的角度:

假设此事某场场次的抢购活动已经开始,我们再看看用户角度的时序图:

输入图片说明

用户点击某个商品的抢购按钮,业务层代码首先去看看抢购计划库此时是否开始(此步可缓存、也可cache在前端页面或Client,若有cache的话,此步可忽略)。若抢购在进行中,此时业务代码需要查询商品在本次抢购中的库存还有否(高频请求,即图中“争取名额”阶段)

“争抢名额”这块,一会我们细讲,先把时序图说完。

若用户抢到了名额,就允许用户跳转到第三方的支付页面产生消费。(此时第三方笑了),产生消费后,第三方自己的库存-1,并且可以实时、异步、完事对账的方式通知我们。

##2.2 如何保证商品库的库存可靠## 我们其实是将商品库的子库前置在业务层抗压力。那么,如何保证大家的库存情况稳定,不会因为抢购业务,导致库存波动影响用户体验。这里就需要提一个业务RD需要关注的问题,需要做好取舍。要么,我们保证大家看到的库存规律一致,要么,我们保证单个用户看到的库存规律一致。若保证大家看到的库存减少的规律一致,且同一时刻库存大家看到的库存都一样。这就对系统有数据强一致性要求,需要很大成本,还只能逐渐逼近此要求要求的效果。而我们若选择后者,仅保证单个用户看到的库存减少规律一致,虽放弃了数据强一致,但以更少的时间尽可能实现了最好的效果。所以,我们用到了用户来排队,若抢到名额了,在抢购库中的库存 –(减减),这样单用户操作期间,能看到规律的减少,不会出现此事看剩10个,一会看还有11个的情况。这时我们说如何内部排队如何来控制“查询商品在本次抢购中的库存还有否(高频请求)”这个高频请求。

输入图片说明

我们构建商品维度的cache,上图中虽然说是“队列”,我们可以用redis的list来真正实现个队列,也可以通过/–来实现。

假设商品A,运营配了20件,此事来了N多用户的请求,业务代码都会来查询cache_prefix_a_id这个队列的长度若队列长度≤0,则有权去–(减减)抢购库的商品库存若队列长度在20件内,则通过业务代码内的等待来等待队头的位置,然后获得抢购权限若队列长度太长,则可以直接返回,认为商品已被抢空

这时插入一个运营配库的时序,便于大家理解。该时序图有详细的说明和标注,就不展开了,如下图:

输入图片说明

此时,我们可以想象,若上游用户的请求压力是N,这个N会压在业务层的抢购库,俗话说“责任止于此”。

##2.3 如何和第三方多方对账## 那么,我们回顾目录“如何和第三方多方对账”? 这里就要提到“Transaction Data”这个库了。

Transaction ID为用户维度的Session记录,用户从进入抢购业务开始,产生一个Transaction ID,该Transaction ID生命周期截止到用户跳转去第三方支付为止。期间在生活服务中产生的浏览、抢购行为均会挂靠到该Transaction ID之下,并会在跳转去第三方支付页时携带该Transaction ID凭证。最主要的是需要记录下:用户获得商品名额后,跳转去第三方时,这一行为

考虑到Transaction ID为抢购业务中,用户操作行为的关键字段,值需要保证唯一。故此处可以采用发号器之类的能力。

我们构建的Transaction Data记录,就可以按照DailyRun的方式,与第三方对账,来fix两方数据库库存不一致等问题。

为什么会产生我们和资源方的库存不一致,可能是因为用户在第三方消费后,第三方callback我们时候失败造成,也可能是因为用户跳去第三方后并没有真正支付,但我们的商品库、抢购库的库存都已经减少造成的。原因可能有很多,对账机制是必要的。

#3 项目总结# 最后,我们回顾回顾设计,压力问题在业务层解决了库存不一致问题我们通过对账机制解决了产品的需求我们也通过旁路可配解决了,嗯,可以喝杯茶,发起评审,评审通过后开始写代码了。

© 著作权归作者所有

共有 人打赏支持
陶邦仁
粉丝 1648
博文 420
码字总数 1483887
作品 0
海淀
技术主管
私信 提问
加载中

评论(3)

m
mitol
请问一下,至于秒杀队列这个,如果我采用单台服务器自己独立维护一个队列,不采用同一个队列的方式来做,会有什么问题?后续预扣库存和其他操作都是采用 redis 的分布式锁来做
陶邦仁
陶邦仁

引用来自“linapex”的评论

总的意思算是看明白了,全靠redis来抗起
redis只是其中一种方式,具体实现要看具体秒杀业务需求。
linapex
linapex
总的意思算是看明白了,全靠redis来抗起
iGeek Camp第四期--北京站

环信作为互联网行业的技术领先者,推出iGeek Camp系列技术活动,旨在以开放的心态,分享深厚的技术积累,推动并打造一个互联网技术创新的平台,iGeek Camp的口号是:交流、分享、融合、创新、协...

Jack
2015/12/16
405
0
iGeek Camp第四期--北京站

环信作为互联网行业的技术领先者,推出iGeek Camp系列技术活动,旨在以开放的心态,分享深厚的技术积累,推动并打造一个互联网技术创新的平台,iGeek Camp的口号是:交流、分享、融合、创新、协...

Jack
2015/12/16
0
0
SpringBoot开发案例从0到1构建分布式秒杀系统

前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路。俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了...

小柒2012
2018/05/16
0
0
高并发场景下秒杀系统的设计思路

1 概述 秒杀系统之所以难做,是因为在极短的时间内涌入大量的请求,来同时访问有限的服务资源,从而造成系统负载压力大,甚至导致系统服务瘫痪以及宕机的可能。本文会介绍秒杀系统中存在的痛...

FEINIK
2018/05/06
0
0
说说网站限时秒杀系统的架构设计

时值双十一在即,各大网站都在争相进行限时秒杀的促销活动。秒杀是一种常见的营销手段,它指的是把少量的商品(一般是一件)以极低的价格,在特定的时间点开始销售。这些商品一般在活动开始的...

deniro
2017/11/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

安装MyEclipse、激活MyEclipse、安装SVN插件

安装MyEclipse 1. 点击下载好的MyEclipse安装程序,弹出如下对话框,点击next 2. 勾选前面的方框,表示同意MyEclipse的协议,然后点击next。 3. 设置安装MyEclipse的路径,最好安装一个盘的根...

三度小姐
8分钟前
0
0
阿里巴巴的微服务开源之路

2019阿里云峰会·北京开发者专场 侠之大者,为国为民。 在金庸小说中,郭靖和黄蓉是“侠之大者,为国为民”的典范,他们以布衣之身帮助宋军守护襄阳十余年。 技术的世界里,并无大小之分。 ...

Mr_zebra
11分钟前
0
0
haproxy

Haproxy是一款免费、稳定、高效的轻量级负载均衡软件,现将其配置文件参数作如下说明: global #全局配置参数 global #全局配置参数 log 127.0.0.1 local3 info #日志级别 ...

拜了个拜
12分钟前
1
0
springmvc源码解析之@EnableWebMvc六

说在前面 本次主要介绍springmvc配置解析。更多精彩请关注“天河聊架构”微信公众号。 springmvc配置解析 @EnableWebMvc这个注解干了什么,初始化ViewResolver 进入到这个方法org.springfra...

天河2018
16分钟前
0
0
回调函数的那些事儿

实际工作中,对于回调函数一直是我不愿意去触碰的东西,一来由于被很多人搞得神秘兮兮的以为是很高深难懂的技术,二来在一般情况下通过互相包含类指针也能够解决问题,所以一直就不想去研究这...

rainbowcode
17分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部