架构实战营-毕业设计
设计电商秒杀系统
【业务背景】
你作为一个电商创业公司的架构师,负责设计 6.18 大促秒杀系统的设计,你们的业务模式如下:1. 你们挑选选品各大电商平台上畅销和好评的商品进行销售,每个品类不超过 20 个商品,目前做了 10 个品类;
2. 本次 6.18 秒杀选择了 1000 个充电宝,10 台 iPhone12 作为秒杀商品;3. 正常的日活大约 100 万用户;4. 老板要求万无一失。
【技术背景】
1. 技术团队以 Java 为主,已经落地了微服务架构;2. 主要渠道是自有的 App(包括 iOS 和 Android)和微信小程序,为了促进用户转化为 App 用户,只有下载 App 才能参加秒杀活动;3. 目前只有单机房。
【毕设要求】
1. 设计完整的架构,例如存储、负载均衡、缓存、高可用、可扩展等;2. 大约 10 页以内的 PPT,每页 PPT 说明一项设计,包括架构设计和设计理由,无需详细解释备选方案。
【提示】
1. 分析考虑要全面,但并不意味着架构设计要面面俱到,如果分析后认为某些设计点可以不做,就在作业最后统一说明原因即可;2. 如果没有思路,请对照模块 9 的 IM 案例;3. 如果有的信息觉得不够全或者不够细,可以做出一定的假设,但不能天马行空,需要对照已有的业务背景和技术背景进行合理推断。
题目分析
限制因素
-
人力不会很多,不能过度设计。
-
经费不会特别充足,需要考虑成本。
-
单机房,云上还是 IDC,假设是 IDC。当流量洪峰到达时,IDC 没办法快速扩容。如果提前采购了机器,但是又不会一直使用。造成资源浪费。所以可以使用云上资源来部署秒杀活动的服务。
-
团队偏向 Java 技术栈,已经落地了微服务架构,微服务框架使用 springcloud。
-
秒杀入口是自家的 APP,但由于秒杀只允许 APP 访问,可以提供应用商店和官网两个渠道的下载途径。
业务分析
-
题目中所述的 DAU 为约 100 万,秒杀场景不同于以往, 假设参与人数达到日活的5倍,约500万参加,浏览商品集中在秒杀前的一分钟前到达最高,则这一分钟的qps为 500万/60约等于9万/s。
-
目前商品数量不好过 200 个,
-
真正参与秒杀的商品只有 1000 个充电宝和 10 台 iPhone,由于参与秒杀的商品实际上是极少的,因此考虑秒杀系统采用过滤+排队双重措施,过滤将并发降低到 1w,之后限流系统保证请求按照顺序稳定执行,异步通知用户
-
由于秒杀业务是典型的瞬时高并发业务,系统的核心设计是限流和排队组件
正式回答
考虑到毕设背景的公司已经有 100 万的日活用户,已经有了较为成熟的系统来支持日常的业务,因此在秒杀系统中能够复用的就不再重复开发,但还是单独部署。
基本业务场景
![](https://static001.geekbang.org/infoq/0c/0ca425bf866f0672cb4499a0a044afb7.png)
-
用户下载 APP
-
用户登录 APP
-
用户查看秒杀页面,通过秒杀状态查询接口查看秒杀是否开始,若秒杀开始则返回秒杀的接口地址(以免过早暴露导致被脚本攻击)
-
用户通过秒杀接口进行抢购,等待秒杀结果
计算架构设计
计算性能估算
用户下载和登录 APP 是比较分散的,不会对系统产生较大的压力,因此就不详细讨论了,关键在于秒杀状态查询,秒杀抢购的进行。
上面业务分析那节我们已经估算了参与秒杀的人最多不超过 36 万,按照 40 万取整计算。
【秒杀查询】
峰值不超过 40 万。
【秒杀抢购】
峰值不超过 40 万。
核心点:
-
秒杀状态查询是查询,需要借助负载均衡以及缓存实现。
-
秒杀抢购是典型的写操作,因此需要进行排队限流。
缓存设计
基本情况:
-
app 缓存+web 容器缓存+分布式缓存
-
详情页等图片信息采用 APP 缓存+web 容器缓存的方式
-
分布式缓存采用 Redis Cluster,保存秒杀商品库存。
-
秒杀活动页面的静态资源可以预先放在 CDN 缓存上面
![](https://static001.geekbang.org/infoq/4a/4a5c3384bda130c4b15f09a510e057ac.png)
负载均衡设计
-
原有电商系统只用 Nginx 作为网络接入负载,为了应对秒杀的高并发,新增 LVS 来做负载。
-
秒杀系统服务集群前同样配置 Nginx 作反向代理和负载均衡。
-
LVS 对接入流量作区分,如果是秒杀请求,走秒杀服务集群;如果是正常业务请求,走原有的服务集群。
-
在秒杀高并发时保证正常业务的进行。
![](https://static001.geekbang.org/infoq/f8/f8ca1a5fe6d72397f756ca02772fd19a.png)
PS:实际上要是限流技术比较成熟可以考虑通过客户端限流的方式将流量降到 10w 以下,那么负载均衡这块就比较简单了,直接不需要 LVS,直接 Nginx 就可以了。但考虑到时初创团队还是 LVS+nginx 比较保险。
限流设计
-
秒杀服务模块对接 Kafka,秒杀成功下单不直接记录数据库,而是推送到 Kafka。后续由订单服务模块从 Kafka 拿消息,异步处理订单,保存数据库
-
秒杀处理流程:
-
秒杀请求进来 Nginx,Nginx 从 Redis 获取令牌(预先放下商品数量相同的令牌)
-
如果不能获取,返回秒杀终止
-
获取成功,请求进入秒杀服务
-
秒杀服务作校验后(风控),从 Redis 获取库存
-
如果获取库存不成功(商品秒杀完),返回秒杀失败
-
如果获取成功,下单,信息保存在 Kafka
-
订单服务异步从 Kafka 获取下单信息,正式下单,保存订单数据
-
秒杀成功客户后续支付订单,完成
![](https://static001.geekbang.org/infoq/f0/f0c47c573282ed3171dc16dff5ec34b6.png)
存储架构设计
![](https://static001.geekbang.org/infoq/8c/8cc2a35e6df7dcc13372b67de775b6f5.png)
-
存储采用 MySQL 集群+Redis Cluster
-
MySQL 集群沿用现有电商系统,保存最终秒杀的订单记录,数据量同商品数量
-
Redis Cluster 是秒杀系统的核心部分:
-
利用 Redis 的高效,秒杀开始前,商品库存预热保存在 Redis 里,减少库存的操作不经过 MySQL。
-
利用 Redis 的单线程处理的特点,采用漏桶限流算法,进行限流。
-
采用 Redis Cluster 来实现高可用。
总架构图
![](https://static001.geekbang.org/infoq/f4/f4c00d9251cc9585fb7d90548341ba40.png)
其他架构设计
高可用设计
根据秒杀系统的特性,为了节约硬件成本以及与原有服务隔离,因此秒杀系统暂定采用云服务部署。因此暂时不需要考虑同城高可用问题,同时用户量不太多,暂时不考虑混合云高可用。
此外为了保证万无一失,准备秒杀兜底方案,在发生异常情况时,主库被打挂了,无法瞬间解决的情况下,运维平台直接让 Nginx 转发到自建机房中的兜底服务器,连接备库提供服务,这时 Nginx 转发策略将请求限流到 2000 以下,如下图所示。
![](https://static001.geekbang.org/infoq/93/936e6abf2bc9a84abe46049b196fd99a.png)
可扩展设计
上面已经分析过了,作为初创电商公司,投入的技术人员可能不超过 30 个,后端人员算 15 个,根据三个火枪手原则,拆分的服务不宜超过 5 个。
服务拆分如下所示:
-
订单服务
-
商品服务
-
支付服务
-
排队服务
-
运维监控服务
![](https://static001.geekbang.org/infoq/65/6574ae5224b86024d54eb5c358c1d7c3.png)
安全设计
抢购 API 的暴露问题,热点用户监测和处理
可运维性以及可观测性
单独开发运维监控服务来保证可运维性。
-
通过 Prometheus 实现服务的全面监控
-
通过监控运维系统时刻观察参与秒杀的用户数量,以及秒杀排队情况
-
日志,通过 ELK 实现日志的聚合和查看,需要详细的业务日志,可以支持人工回滚
![](https://static001.geekbang.org/infoq/df/df29804cb3b38fb6b5cb9d1cc2448193.png)
总结
由于有专门的毕业总结的文章,我们就不在这里做过多的总结了,果然秒杀还是互联网技术王冠上最璀璨的瑰宝。
参考: