秒杀服务
前言
做业务的都知道:
做系统概念很重要
因为在同事和同事间沟通中,这些概念可以精准的告诉别人你想表达的。尤其是电商系统,众所周知电商里有很多的概念,比如Sku、Spu等。
所以首先我们需要了解秒杀是什么?
秒杀是什么?
我们先来看如下京东、有品、拼多多的秒杀页面截图。
通过页面上的信息我们可以获取到如下的有用信息:
概念 | 描述 |
---|---|
概念1 | 活动 |
概念2 | 场次的概念,场次是活动的子集 |
页面上的数据信息 | 描述 |
---|---|
活动信息 | 活动、场次信息 |
秒杀商品信息 | 商品图片、商品名称、商品加车价格、商品售价、其他描述信息 |
秒杀进度 | 库存进度 |
秒杀的定义:
秒杀是电商的一种营销手段,常见的有一元秒杀等
秒杀活动有哪些营销维度?
营销维度 |
---|
价格维度 |
数量维度 |
商品维度 |
时间维度 |
价格维度 |
---|
白菜价 |
非白菜价 |
数量维度 |
---|
极少(比如几个) |
非极少 |
商品维度 |
---|
爆品 |
非爆品 |
时间维度 |
---|
限时 |
把上面的维度按照运营需求组合就得到了不同的秒杀活动类型,如下:
首先,一元秒杀之类:白菜价+极少+(爆品或者非爆品)+限时
其次,限时购(又称常规秒杀):非白菜价+(极少或非极少)+(爆品或者非爆品)+限时
接着,爆品抢购:非白菜价+(极少或非极少)+爆品+限时
秒杀活动类型 | 营销维度 |
---|---|
一元秒杀之类 | 白菜价+极少+(爆品或者非爆品)+限时 |
限时购(又称常规秒杀) | 非白菜价+(极少或非极少)+(爆品或者非爆品)+限时 -> |
爆品抢购 | 非白菜价+(极少或非极少)+爆品+限时 |
一个简单的秒杀系统
实现原理: 通过redis原子操作减库存
图一
优点 | 缺点 |
---|---|
简单好用 | 考验redis服务能力 |
是否公平 |
---|
公平 |
先到先得 |
我们称这类秒杀系统为:
简单秒杀系统
如果刚开始QPS并不高,redis完全抗的下来的情况,完全可以依赖这个「简单秒杀系统」。
一个够用的秒杀系统
实现原理: 服务内存限流算法 + redis原子操作减库存
图二
优点 | 缺点 |
---|---|
简单好用 | - |
是否公平 |
---|
不是很公平 |
相对的先到先得 |
我们称这类秒杀系统为:
够用秒杀系统
性能再好点的秒杀系统
实现原理: 服务本地内存原子操作减库存
服务本地内存的库存怎么来的?
活动开始前分配好每台机器的库存,推送到机器上。
图三
优点 | 缺点 |
---|---|
高性能 | 不支持动态伸缩容(活动进行期间),因为库存是活动开始前分配好的 |
释放redis压力 | - |
是否公平 |
---|
不是很公平 |
不是绝对的先到先得 |
我们称这类秒杀系统为:
预备库存秒杀系统
支持动态伸缩容的秒杀系统
实现原理: 服务本地协程Coroutine定时redis原子操作减部分库存到本地内存 + 服务本地内存原子操作减库存
图四
优点 | 缺点 |
---|---|
高性能 | 支持动态伸缩容(活动进行期间) |
释放redis压力 | - |
具备通用性 | - |
是否公平 |
---|
不是很公平,但是好了点 |
几乎先到先得 |
我们称这类秒杀系统为:
实时预备库存秒杀系统
公平的秒杀系统
实现原理: 服务本地Goroutine定时同步是否售罄到本地内存 + 队列 + 排队成功轮训(或主动Push)结果
图五
优点 | 缺点 |
---|---|
高性能 | 开发成本高(需主动通知或轮训排队结果) |
真公平 | - |
具备通用性 | - |
是否公平 |
---|
很公平 |
绝对的先到先得 |
我们称这类秒杀系统为:
公平排队秒杀系统
骚操作
上面的秒杀系统还不够完美吗?
答案:是的。
还有什么优化的空间?
答案:静态化获取秒杀活动信息的接口。
静态化是什么意思?
答案:比如获取秒杀活动信息是通过接口 https://seckill.skrshop.tech/v1/acticity/get
获取的。现在呢,我们需要通过https://static-api.skrshop.tech/seckill/v1/acticity/get
这个接口获取。有什么区别呢?看下面:
服务名 | 接口 | 数据存储位置 |
---|---|---|
秒杀服务 | https://seckill.skrshop.tech/v1/acticity/get | 秒杀服务内存或redis等 |
接口静态化服务 | https://static-api.skrshop.tech/seckill/v1/acticity/get | CDN、本地文件 |
以前是这样
变成了这样
结果:可以通过接口https://static-api.skrshop.tech/seckill/v1/acticity/get
就获取到了秒杀活动信息,流量都分摊到了cdn,秒杀服务自身没了这部分的负载。
完整流程方案①
完整流程主要涉及三个接口:
秒杀服务接口 | 对内还是对外 | 描述 |
---|---|---|
秒杀信息获取接口 | 对外 | QPS要求高、所以可以直接对外 |
获取秒杀资格 | 对外 | 用户获取加入此商品加入购物车的资格 |
校验并获取秒杀价格接口 | 对内 | 购物车接口校验资格,并返回该商品当前活动的秒杀资格 |
完整流程方案②
这个方案和上面的有什么区别呢?答:把获取秒杀活动信息的接口统一收敛到了「营销中心」,目的:
把所有的营销活动都抽象到一个「商品活动信息」的接口
这样,我们的商品详情页面的读的逻辑就很清晰,如下:
- 第1类:商品基础信息接口,获取商品的基础信息(图片、名称、描述、价格、库存等等)
- 第2类:商品活动信息接口,获取该商品参加的所有营销活动信息(满减、满赠、买送、秒杀等等)
图示:
总结
上面我们得到了如下几类秒杀系统
秒杀系统 | ||
---|---|---|
简单秒杀系统 | ||
够用秒杀系统 | ||
预备库存秒杀系统 | ||
实时预备库存秒杀系统 | ||
公平排队秒杀系统 |
我想说的是里面没有最好的方案,也没有最坏的方案,只有适合你的。
拿先到先得
来说,一定要看你们的产品对外宣传,切勿上来就追逐绝对的先到先得。其实你看所有的方案,相对而言都是“先到先得”,比如,活动开始一个小时了你再来抢,那相对于准时的用户自然抢不过,对吧。
又如预备库存秒杀系统
,虽然不支持动态伸缩容。但是如果你的环境满足如下任意条件,就完全够用了。
- 秒杀场景结束时间之快,通常几秒就结束了,真实活动可能会发生如下情况:
- 服务压力大还没挂:根本就来不及动态伸缩容
- 服务压力大已经挂了:可以先暂停活动,服务起来&扩容结束,用剩余库存重新推送
- 运维自身不具备动态伸缩容的能力
所以:
合适好用就行,切勿过度设计。