秒杀系统总体方案目标与架构设计
在前面的文章中,梳理了秒杀系统的需求和业务流程,并对秒杀系统的技术流程进行了总体梳理,不管是从业务角度出发,还是从技术角度出发,都大致了解了秒杀系统的执行流程。从业务和技术角度了解秒杀系统的执行流程后,接下来,就要制定方案目标和总体架构设计了。
一、前言
相信很多小伙伴都有多这样的体会,接到需求后,如果不做全面的需求分析、系统分析和架构设计,一上来就干代码,往往在开发中途就会发现代码不太符合需求,或者突然发现有更好的实现方式,大部分时候,已经来不及将代码推倒重来,只能在原有代码的基础上苦苦支撑。最终,原本设想的高并发、高性能、高可用和高可扩展的代码,却变成了一坨 “屎山”。
二、本章诉求
作为系统架构师和研发人员,在充分了解了系统需求、业务流程和技术流程后,就需要为系统设定方案目标,制定技术方案选型,对系统进行总体架构设计和分层架构设计。从全局视角充分理解秒杀系统的方案目 标、技术选型、总体架构和分层架构,以指导后续秒杀系统的具体实现。
三、方案目标
在进行技术选型和总体架构设计之前,需要明确一个事项,就是系统无论采用何种方案,采用何种架构设计都需要明确这种方案的业务目标、技术目标和架构目标,并在研发过程中不断评估系统的总体性能表现,发现系统瓶颈并不断进行优化。
总体上,无论采用何种方案实现秒杀系统,都要实现如下方案目标。
- 业务目标:满足用户故事中的各类场景。
- 技术目标:秒杀商品详情页接口:10W+QPS,秒杀接口:1W+TPS。
- 架构目标:高并发、高性能、高可用、可监控、可预警、可伸缩。
四、技术选型
在技术选型上,除了采用 SpringBoot 等基础框架外,也会采用容器化方案。为了尽量降低技术门槛,在整个秒杀系统的技术选型中,主要采用市面上比较主流的技术框架和方案,具体技术选型如下所示。
- 开发框架:SpringBoot。
- 缓存:Redis + 本地缓存。
- 数据库:MySQL。
- 业务网关:SpringCloud Gateway。
- 持久层框架:MyBatis。
- 服务配置与注册发现:Nacos。
- 容器:Docker。
- 容器化管理:Swarm、Portainer。
- 监控:Prometheus、Grafana。
- 系统限流:Nginx+Lua、Sentinel。
- 消息中间件:RocketMQ。
- 单元测试:Junit。
- 压测工具:JMeter。
五、一般系统架构设计
如果是按照一般系统的架构设计方案来设计秒杀系统的话,相信大部分小伙伴会将秒杀系统的架构设计成如图 6-1 所示。

这种架构设计也是比较常见的,在这种架构设计中,Nginx 只做负载均衡和反向代理,研发人员更多的是关注 Web 服务层和基础服务层的开发。虽然这种架构设计在一般的系统中没什么问题,但是放到秒杀系统中,会存在很多问题。
(1)Web 服务性能问题
Nginx 只提供负载均衡与反向代理的功能,大部分流量会直接进入 Web 服务层,Web 服务层一般会采用 Tomcat 作为服务器。了解 Tomcat 的小伙伴都知道,Tomcat 是通过线程池来处理请求。如果大部分流量都直接涌入 Tomcat 的话,Tomcat 就会瞬间接收大量的请求,如果 Tomcat 线程池中的线程设置的比较小,很容易导致 Tomcat 线程池中的线程不够用,继而 Tomcat 中线程池的等待队列会被占满,后续的请求会被拒绝,并且 Tomcat 会持续高负载运行,最终导致系统卡顿。如果 Tomcat 线程池中的线程数设置的过大,很容易将 CPU 打满,到时机器卡死,即使没有卡死,当 Tomcat 中线程池的等待队列被占满后,后面的请求也会被拒绝掉,总体上的表现就是性能很差,并且会有很多请求被拒绝掉。
(2)拉取资源填充数据性能问题
这种架构设计无论是将静态资源放在 Nginx 中,还是放到 Web 服务层,对会表现的比较卡顿。因为大量请求涌入 Web 服务层,会大量的调用相关的接口,导致 Web 服务层变得卡顿,后续请求进入系统后,加载静态资源,例如静态页面后,静态页面会调用接口获取数据,由于接口此时变得非常卡顿,就会导致静态资源上的数据加载缓慢,直接表现就是页面无法正常加载,拉取资源填充数据性能很差。
六、秒杀系统总体架构设计
可以在一般系统架构设计的基础上,进行优化设计,来满足秒杀业务场景的需求,优化后的秒杀系统屏蔽掉技术细节的架构设计如图 6-2 所示。

对比图 6-1 和 6-2 可以看出,在屏蔽掉技术实现细节的前提下,在秒杀系统的架构设计中,会将静态资源放到 CDN。并且对业务校验和流量管控进行前置化,放大 Nginx 的职责。使得 Nginx 不仅具备反向代理和负载均衡的功能,还能实现限流、黑白名单、流量管控、业务校验等,并且在 Nginx 层面也能实现直接查询商品数据返回给客户端。
也就是说,在这种架构模式下,充分利用 Nginx 的高并发、高吞吐的能力,尽量将大部分刷单流量和无效请求拦截在 Nginx 层,使得进入系统的流量是真正的有效流量,这样会大大减轻业务系统的压力。
除了在 Nginx 中实现限流、黑白名单、流量控制、业务校验等功能外,为了进一步保证下游系统的安全,在 Web 服务层也可以实现限流、降级、流控、业务校验、服务降级等流量管控措施。
经过一系列的流量处理措施,进入基础服务层面的流量已经相对比较小和可控了。那么问题来了:这种架构设计还有进一步优化的空间吗?
七、秒杀系统容器化架构设计
为了进一步增强秒杀系统的性能、可用性和弹性伸缩性,可以对秒杀系统的架构设计进行进一步优化,采用容器化架构设计,如图 6-3 所示。

由图 6-3 可以看出,对秒杀系统进行容器化架构设计优化之后,总体上会分成客户端、流量入口、系统网关、应用服务、容器化和基础支撑服务等。
(1)客户端
客户端主要包括 PC、H5、APP 和小程序,可以将 PC 和 H5 等静态资源发布到 CDN 服务器,来加速静态资源的加载速度。
(2)流量入口
主要由 Nginx 负责流量的入口,此处同样会放大 Nginx 的职责,除了常规的反向代理和负载均衡外,Nginx 还会提供限流、黑白名单、流量控制、业务校验和商品数据查询等功能。也就是说,在 Nginx 层会做一些业务逻辑处理。
(3)系统网关
系统网关层除了做路由功能外,还提供限流、熔断、鉴权与安全的功能,可以使用 SpringCloud Gateway 结合 Sentinal 实现。
(4)应用服务
在应用服务层,除了做业务开发外,需要考虑本地缓存、分布式 缓存、缓存数据一致性,这里缓存数据一致性包括本地缓存与分布式缓存,缓存与数据库数据的一致性问题。同时,在应用服务层采用动静分离的模式,将动态资源与静态资源进行隔离,并进行业务校验与业务隔离,在数据的序列化与反序列化上进行优化。同时在业务处理层面,尽量做到数据精简和简化相关的计算逻辑。
(5)容器化
在容器化层面,会通过 Docker、Swarm 和 Portainer 实现,其中,会基于 Swarm 和 Portainer 对容器化进行管理。
(6)基础支撑服务
基础支撑服务层主要是由一些基础的中间件实现,包括:MySQL 数据库、Redis 缓存、RocketMQ 消息队列、Prometheus 监控和 Portainer 容器管理等基础中间件实现,基础支撑服务会对整个秒杀系统提供最基础的数据、传输、监控和容器管理等服务。
(7)其他功能实现
除了上述分层架构外,对于建设秒杀系统来说,还要考虑异常监控、服务注册与发现、可视化、服务降级与兜底数据、服务限流、服务容灾、容量规划与扩缩容和全链路压测等。
八、DDD 分层业务架构设计
对于秒杀系统的代码业务层,可以借鉴 DDD 的分层架构思想,将代码总体上分成展示层、应用层、领域层和基础设施层四个层次,如图 6-4 所示。

这里,秒杀系统会借鉴 DDD 的设计思想,但是不会完全按照 DDD 的方式进行设计。
(1)展示层
展示层,也叫做用户 UI 层,是 DDD 设计的最上层,对外提供 API 接口,接收客户端请求,解析参数,返回结果数据,并对异常进行处理。
(2)应用层
应用层,也叫做 Application 层,应用层主要处理容易变化的业务场景,可对相关的事件、调度和其他聚合操作进行相关的处理。
(3)领域层
领域层,也叫做 Domain 层,领域层可以说是 DDD 设计的精髓所在,它是将业务系统中相 对不变的部分抽象出来封装成领域模型。
在秒杀系统的设计中,领域层基本不会依赖其他层,也不会依赖基础设施层,这里是与 DDD 设计存在区别的地方。
(4)基础设施层
基础设施层,也叫做 Infrastructure 层,基础设施层会对其他各层提供通用的基础能力,在秒杀系统中,就包括了缓存、通用工具类、消息、系统的持久化机制等。
九、总结
本章,主要对秒杀系统的总体方案目标和架构设计进行了详细的阐述。首先确定了方案的目标并对系统的技术选型进行了描述。在阐述秒杀系统的架构设计时,首先介绍了一般系统的架构设计,指出了一般系统的架构设计在秒杀场景下的不足,并基于一般系统的架构设计升级优化,对秒杀系统的总体架构设计进行了阐述。为了进一步增强秒杀系统的性能、可用性和弹性伸缩性,对秒杀系统的架构设计进行了进一步优化,采用容器化架构设计。最后,在业务代码层面,阐述了 DDD 分层的业务架构设计。