前置准备:架构设计方法论

文章目录

架构设计最忌讳的其实就是什么一开始没有充分思考,直接上面就想当然设计,这样设计出来的系统一定是漏洞百出的,要做一个好的架构设计,我觉得核心有两点:

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 ,所以很多业务的存储就是这两个组件打配合,当然,是不是用他们还是要看前面说的各方面的要求,他们是否满足,以及和其他一个存储方案进行一个对比。

流程串联

服务层次设计好了,存储也选定了,最后需要做的就是将他们串起来,一般可以以一个流程为例,比如发起秒杀这个流程,如果流程很丝滑地能梳理完成,那么这个架构就不会有大问题

同时这个过程中,就要开始考虑对难点、要点进行详细分析,每个系统难点要点都有区别,但也有规律。无非是核心流程细节、高并发、高精准等。

比如我们这里的秒杀,难点无非是高并发和高精准。

那我们就需要去展开高并发的解决方案,去对比,去决策。

高精准的话需要考虑到超卖、少卖问题,以及各种异常情况下,是否有机制能兜底。

优化阶段

做了初步的架构设计之后,我们还需要整体复盘以及优化点考虑,这个过程下是检查我们的设计有没有比较明显的漏洞,我们的架构是不是具备扩展性,还有哪些潜在的优化点。

架构复盘,我们首先要做的,就是复盘我们上面的设计思路是不是能实现功能的,在脑海中或者纸上画一画,看这个架构是不是真的能很好应付秒杀流程,以及存储的选型是不是足够合理。

潜在优化点考虑,除了但是我们前面也分析了,我们是瞬时流量场景,这种场景下,消息队列是否有应用场景呢?是不是能进一步提高性能呢?这些我们都需要考虑,即使第一版本不一定实现,但是心里是要有数的。

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

相关推荐
geovindu1 小时前
java: Task Scheduler
java·开发语言·后端
代码不停1 小时前
Spring Boot 配置文件
spring boot·后端
IT_陈寒2 小时前
为什么我的Java Stream操作总是默默吃掉异常?
前端·人工智能·后端
江湖十年2 小时前
Go 虚荣域名详解:我用 go get -x 抓了个包,终于看清了 Go 工具链“对暗号”的全过程
后端·面试·go
Lost of 程序猿2 小时前
船岸数据同步链路实战:SendFlag、单调版本号与断网三天后的续传
后端·c#·asp.net
卷无止境2 小时前
大模型如何调用工具,一次讲清背后的技术门道
后端·python
90后的晨仔3 小时前
Python 进阶:海象运算符与模式匹配,让你的代码更优雅!
后端
卷无止境9 小时前
智能体开发环境ADE浅析,编程工具的下一次范式跃迁
后端·python
码事漫谈12 小时前
DeepSeek 这波操作很凶
后端