电商秒杀系统架构设计
前言
本文以一个 6.18 大促虚构的秒杀场景,来设计一个秒杀系统,本架构设计文档用于描述我们虚构的秒杀系统的边界,用于指导后续秒杀系统的开发。
此文章为《架构训练营毕业总结》。
1.业务背景
我们的核心业务是通过挑选各大电商平台上畅销和好评的商品进行销售,每个品类不超过 20 个商品,目前做了 10 个品类,日活用户 100 万;在此次 6.18 大促中,我们决定增加一个秒杀模块,同时选择了 1000 个充电宝,10 台 IPhone12 作为秒杀商品。公司希望通过秒杀活动拉新促活,同时带来其它品类的销售增长,因此老板非常看重这个项目,要求做到万无一失。
2.约束和限制
目前主要渠道是自有的 APP 和微信小程序,为了促进 APP 转化只有下载 APP 才能参加活动
目前的技术团队以 Java 为主,使用阿里云,已经落地了微服务
目前使用阿里云的服务
3.总体架构
3.1 架构分析
3.1.1 业务风险
对于秒杀系统来说,如果发生超卖比较严重的一个事情,当发生超卖时容易引起用户不满,产生大量的用户投诉,严重还会有法律风险,因此不能发生超卖时系统可用性首要要保障的事情。
3.1.2 安全风险
当秒杀开始时,采用不正当竞争手段比如使用机器进行秒杀,系统也应该予以制止,保障其公平性,因此秒杀系统安全性也是要重点考虑的事情。
3.1.3 可用性要求
当秒杀活动开始时,如果系统出现故障将严重影响 APP 声誉,甚至造成用户流失,因此系统的高可用是基本要求。然而如果出现极端意外情况,系统无法运行,应对用户进行友好的提示,引导用户继续等待,直到系统恢复,通常情况下秒杀的场景用户出于对活动的兴趣能够容忍 1 分钟内的等待,因此系统在极端的意外情况下允许有 1 分钟的恢复时间。
3.1.4 性能的要求
当秒杀活动开始时,会有大量的用户瞬间涌入,我们根据日常 UV 加上活动推广,我们预计会有 5%的站内用户会参与秒杀活动,同时活动会吸引 5 万新注册用户,因此在活动开始时会有 10 万的 TPS 请求,为了避免估算不准确,我们在预留 50%的空间,系统设计时要能够承担 15 万 TPS 的请求。
3.1.5 对关联系统的要求
秒杀活动开始前,会有大量的用户访问商品详情页,用户在等待秒杀开始前还有可能不断的刷新,因此商品系统要做好应对大量的读请求的准备。
3.2 总体架构
3.2.1 业务架构图
秒杀在整体业务中作为一种商品购买形式的扩充,与拍卖、直购一样是一种购买形式。
3.2.2 系统架构图
系统架构图
负载均衡架构图
秒杀业务关系图
秒杀系统作为新的商品购买形式的实现,因此在商品、订单、库存等系统上都复用于现有的系统,只针对秒杀的场景进行修改,不用另做开发。
通过排队与秒杀两个业务模块来缓冲秒杀开始时的海量请求,而订单的生成以及库存的管理都交由现有的系统完成。
4 核心功能
4.1 秒杀业务处理流程
秒杀业务处理时序图时序图
4.1.1 请求排队
在时序图的第一阶段(1.x)中,秒杀服务器通过使用队列服务将海量的请求进行入队操作,此阶段目的是使用高效的队列服务进行请求缓冲。
4.1.2 获取请求
在时序图的第二阶段(2.x)中,秒杀服务通过检查库存与自身的处理能力,从队列服务中获取相应数量的请求,并为这些请求创建对应的 token,token 是用于安全验证的令牌,防止恶意的请求,当库存为 0 时,标记秒杀结束。
4.1.3
在时序图的第三阶段(3.x)中,客户端通过排队号查询 token,如果获取到 token,说明排队完成,可以发起下单请求,如果查询 token 返回秒杀结束,停止轮询。
4.1.4
在时序图的第三阶段(4.x)中,客户端传入排队获取的 token,秒杀服务验证 token,并将下单请求,转发到订单服务进行处理,订单处理成功会调用库存服务减库存。
4.2 关键设计
4.2.1 队列服务
队列服务作为缓冲请求的第一道关卡,它将直面海量的突发请求。依据我们预估的请求量与业务,我们使用先进先出的队列模型,队列服务将承受每秒 15W 次的写入,且应具备高可用特性。
4.2.2 缓存服务
在我们的业务中,用户轮询去缓存服务获取请求的 token,根据我们的业务预估缓存服务每秒将承受 15W 次的请求,且应具备高可用特性。
4.2.3 秒杀服务
秒杀服务作为请求的接入服务,根据我们的业务预估将承受 15W 次的请求,因此我们的网络模型需要支持海量的连接。
4.3 设计规范
4.3.1 队列服务与缓存服务选型
考虑到尽可量依赖少的服务,同时队列服务于缓存服务的请求是有顺序关系的,两者不会出现请求的累加(不会 15W + 15W 变成 30W QPS),因此可以选用 Redis 同时作为队列服务与缓存服务,使用 Redis List 数据结构提供队列服务,使用 Redis Hash 提供缓存服务;阿里云社区版的 Redis 采用单线程模型,无法满足 QPS10 万+的场景,因此队列服务使用阿里云(Redis企业版性能增强型) 同时考虑到高可用的特性,可以选用“双机热备架构”的模式,在主节点宕机后实现秒级切换,可以满足我们业务需要。
注:在 3.1.3 中所描述,我们也为极端情况下允许 1 分钟的宕机
4.3.2 秒杀服务选型
秒杀服务需要支持海量的连接,同时还需要考虑易开发的特性;在支持海量连接上不能考虑传统的 TPC,prethread 网络模型,应该考虑 reactor 网络模型,netty 是 reacotr 网络模型高性能服务器的代表,直接在 netty 基础上做业务开发不是很合适,因此选用 Spring Boot Webflux 作为秒杀服务的开发框架,Spring Boot Webflux 底层网络框架是基于 Netty 实现的,这样可以发挥 Netty 与 Spring 的优势。
5. 质量设计
在整个秒杀系统的构建中,只引入了一个服务于一个组件(Redis),秒杀服务采用 Spring Boot 框架进行开发于现有系统保持一致,系统可维护性可以得到保障。
5.1 秒杀服务
秒杀服务采用 Spring Boot 进行开发,复用现有系统的持续集成框架以及指标采集、监控得基础组件,可维护性与可测试性得以保障,另外秒杀采用 Spring Webflux 框架,按照单机 1500 连接设计,仅需 10 台 2C4G 的阿里云标准 ECS 即可。
5.2 队列服务
队列服务采用阿里云企业版 Redis 双机热备架构,无须选用集群架构,满足业务需求的同时节约了成本。
5.3 缓存服务
缓存服务于队列服务公用一个 Redis,采用阿里云企业版 Redis 双机热备架构。
6. 总结
本架构设计文档,通过模拟一个 6.18 虚构的秒杀场景,来思考如何做出合适的架构。
在业务背景上,是新增一种业务形态,因此要不用大刀阔斧的把秒杀周边系统全都折腾一遍,如果能够在现有的技术框架内完成新的秒杀业务,那么将减少很多协调、研发成本。因此秒杀系统设计时并未考虑在订单系统中实现秒杀的部分功能,而是将所有秒杀相关的功能内聚在一个系统的完成。
百万日活的电商整体架构运维人员有限,如果能够用一个组件完成的事情,尽量用一个组件完成,减少运维成本,研发成本,比如在队列选型时,能够用 redis 的 list 就没有必要再引入 kafka。
秒杀架构的核心是排队与同步转异步,排队解决的应对海量的并发请求,将请求接收住,同步转异步是在客户端将请求拆分为不同的阶段,以适应服务端秒杀处理不同阶段的设计。
并发的压力来自于整个请求链路的各个环节,不是 Redis 牛了,整个系统就没有问题了,因此应该在各个环节考虑是否能够接收住瞬时的大并发,比如使用 Netty 实现的 Reactor 网络模型。
备注
此架构文档描述的时就秒杀系统后端而言的技术选型与设计工作,没有描述前端的设计以及系统流量负载均衡层的设计。
根据次文档的秒杀系统实现
评论