文章目录
- 准备阶段
-
- [1. "多卖"是什么意思](#1. “多卖”是什么意思)
- [2. "少卖"是什么意思](#2. “少卖”是什么意思)
- 为什么说"少卖看看情况"?
-
- [情况 A:卖出了 10,005 台](#情况 A:卖出了 10,005 台)
- [情况 B:只卖出了 9,995 台](#情况 B:只卖出了 9,995 台)
- 设计阶段
- 优化阶段
架构设计最忌讳的其实就是什么一开始没有充分思考,直接上面就想当然设计,这样设计出来的系统一定是漏洞百出的,要做一个好的架构设计,我觉得核心有两点:
1.一定要做好足够的准备工作,包括信息收集、包括技术调研
2.有一套方法论,成本系统地去进行设计,这里提供一套设计方法,大的方向分为准备阶段和设计阶段和优化阶段。准备阶段分为诉求摸底、请求量确认、精准性深究以及难点要点分析;设计阶段又分为上下游服务分析,存储选型、流程串联;最后的优化阶段分为设计复盘和潜在优化点考虑。

准备阶段
架构设计也不是一开始就设计,一定要做一些准备工作:
1.诉求摸底,摸清整体诉求,了解清楚是做什么,业务流程是怎样,核心功能点要设计啥
2.请求量确认,QPS【Query per second】(1k,10k,100k的做法是不一样的),不同请求量的方案可以说天差地别,实际工作中不能低估请求量,需要适当高估留点buffer,但同时也不能大炮打蚊子,比如让你设计一个1000/s的秒杀系统,你整个10台Redis集群就不合适了,更专业一点来说并发量也是需要考虑的,但是通常说qps就够了,不用那么复杂
3.精准性深究,对于秒杀系统而言,就是能不能多卖、能不能少卖,多卖肯定是不允许的,少卖看看情况
4.难点要点分析,分析一波难点要点,这对梳理设计有好处,后面也会给大家展开讲秒杀的核心难点
"能不能多卖" = 会不会超卖
"能不能少卖" = 会不会少卖
1. "多卖"是什么意思
假设库存只有:
库存 = 100 件
但秒杀结束后系统成功创建了:
101 个有效订单
这就叫多卖 / 超卖。
也就是:
实际卖出去的数量 > 实际库存数量
例如最后一件商品,同时来了两个请求:
请求 A:读取库存 = 1
请求 B:读取库存 = 1
A:库存 - 1 → 成功
B:库存 - 1 → 也成功
结果:
1 件商品
却卖给了 2 个人
这是秒杀系统非常严重的问题,因为你已经对两个用户承诺"购买成功",但实际上只有一件货。
所以:多卖肯定是不允许的。
秒杀系统设计时通常必须保证:
成功订单数 <= 库存数
2. "少卖"是什么意思
还是:
库存 = 100 件
结果秒杀结束:
只成功卖了 98 件
但实际上还有:
2 件库存没有卖出去
与此同时可能还有很多用户在抢。
这就是少卖。
也就是说:
明明有库存,而且存在购买需求,但因为系统设计或异常,库存没有被充分卖出去。
比如:
用户 A 抢到库存
↓
Redis 库存从 1 → 0
↓
准备创建订单
↓
服务突然宕机
↓
订单没创建成功
这时候可能出现:
Redis:库存 = 0
实际上:
没有任何用户真正买到最后这一件商品
于是这件库存相当于被"占住"或者丢失了。
这就是一种少卖。
为什么说"少卖看看情况"?
因为超卖和少卖的严重程度不一样。
假设小米秒杀 10,000 台手机:
情况 A:卖出了 10,005 台
库存只有:
10000
却收到了:
10005 个成功订单
意味着有 5 个用户已经付款或者下单成功,但你没有货给他们。
这是比较严重的业务事故。
情况 B:只卖出了 9,995 台
还剩:
5 台
没有成功卖出去。
这种情况虽然不好,但很多业务是可以接受的。
因为这 5 台可以:
库存回滚
↓
重新释放
↓
下一轮继续卖
或者直接人工补偿。
所以架构设计里经常会有一个原则:
宁可少卖,也不能超卖。
尤其是秒杀场景。
设计阶段
有了前置准备,我们就可以进行架构设计了,架构设计是大方向的把握。
对整个系统的架构进行设计有点无从下手是吧?那么我们可以化整为零,拆分一下。
什么是架构?核心不过是服务+存储+流程,你有哪些服务,存储用的是什么,结合业务流程这些服务、存储如何串联起来?
上下游服务分析
我们需要去分析我们的服务分几层,会涉及到哪些上下游服务。
秒杀场景下,我们涉及到的服务,可能会很多,比如商品信息服务、秒杀服务、库存服务、订单服务、支付服务等等。在大公司大团队里,它们通常都是非常独立的微服务,但在中小型团队,拆得不会这么细,微服务拆得太多其实是灾难。因为每个服务都需要人维护,太多就麻烦,容易出问题。 而且改动实现一个简单需求你都不得不改动多个服务
存储选型
后端开发一个很重要的职责就是跟数据打交道,要把数据存起来。
存储选什么呢?影响因素有很多,包括存储场景、可靠性、性能要求、团队技术栈、我们需要综合性考虑,才能确定存储选型。
比如,最常用的,高性能需要Redis、高精准需要MySQL ,所以很多业务的存储就是这两个组件打配合,当然,是不是用他们还是要看前面说的各方面的要求,他们是否满足,以及和其他一个存储方案进行一个对比。

流程串联
服务层次设计好了,存储也选定了,最后需要做的就是将他们串起来,一般可以以一个流程为例,比如发起秒杀这个流程,如果流程很丝滑地能梳理完成,那么这个架构就不会有大问题。
同时这个过程中,就要开始考虑对难点、要点进行详细分析,每个系统难点要点都有区别,但也有规律。无非是核心流程细节、高并发、高精准等。
比如我们这里的秒杀,难点无非是高并发和高精准。
那我们就需要去展开高并发的解决方案,去对比,去决策。
高精准的话需要考虑到超卖、少卖问题,以及各种异常情况下,是否有机制能兜底。
优化阶段
做了初步的架构设计之后,我们还需要整体复盘以及优化点考虑,这个过程下是检查我们的设计有没有比较明显的漏洞,我们的架构是不是具备扩展性,还有哪些潜在的优化点。
架构复盘,我们首先要做的,就是复盘我们上面的设计思路是不是能实现功能的,在脑海中或者纸上画一画,看这个架构是不是真的能很好应付秒杀流程,以及存储的选型是不是足够合理。
潜在优化点考虑,除了但是我们前面也分析了,我们是瞬时流量场景,这种场景下,消息队列是否有应用场景呢?是不是能进一步提高性能呢?这些我们都需要考虑,即使第一版本不一定实现,但是心里是要有数的。
之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!