05.秒杀系统架构
# 01.需求分析
# 1、功能需求
“秒杀”这个词在电商行业中出现的频率较高,如京东或者淘宝平台的各种“秒杀”活动,最典型的就是“双11抢购”
“秒杀”是指在有限的时间内对有限的商品数量进行抢购的一种行为,这是商家以“低价量少”的商品来获取用户的一种营销手段
其实,整个秒杀的业务场景并不复杂,可即查看参与秒杀的商品信息,加上购买和支付的动作,如下图所示
秒杀业务最大的挑战在于3点:
**瞬时:**持续时间极短,对于热门且具备极强竞争力的商品通常只有一秒
**流量巨大:**因为价格低廉,商品性价比高,而且正常买是需要很高的价格,所以才会吸引大量的用户来争抢
**数量有限:**因为商品的低价且性价比高,所以只有很有限的商品数量参与秒杀
防止遭到恶意破坏等,特此增加如下需求
1)用户在秒杀页面无需一直刷新“抢购”按钮,待秒杀活动开始时,按钮自动点亮
2)在公平以及防止恶意破坏的原则下,在下单之前增加验证码的录入,或者答题的相关环节
3)库存不能出现问题,即不多扣也不少扣
4)整个秒杀活动过程持续10分钟
# 2、性能指标预估
- 通过秒杀的需求描述可得出,当前秒杀活动主要需要预估三块的性能指标:存储容量、并发量、网络带宽
1)存储容量
- 由于是秒杀活动,且参与的商品基本都是低价高性价比的,数量是非常有限的
- 所以,在订单存储上基本不用去过多考虑
2)并发量
- 针对5000万用户平均每人访问2次,则并发量为每秒16.7万左右(
5000w*2/10*60
) - 在预留一部分,可以预估到每秒25万左右(也可以进行double下)
- 针对5000万用户平均每人访问2次,则并发量为每秒16.7万左右(
3)网络带宽
- 在带宽方面,需要进行相关优化,采取数据传输越少越好
- 假设
单条
传输在0.5KB
,则根据并发量预估网络带宽为:977Mb
左右(25w*0.5KB=122MB*8bit=977Mb
)
# 02.功能设计
# 0、分层结构图说明
# 1、浏览器端优化
静态资源缓存:
- 利用浏览器缓存机制缓存静态页面、CSS、JS等资源,减少不必要的重复请求和服务器压力
- 同时,确保缓存策略能自动清除旧的资源缓存(如利用版本号或hash机制)
购物车缓存与校验:
- 将用户的购物车信息缓存到浏览器本地(如使用
localStorage
) - 在用户完成购买前校验库存,避免用户提交无效订单
- 将用户的购物车信息缓存到浏览器本地(如使用
预加载与占位符:
- 通过预加载图片、静态资源,减少秒杀页面的加载时间
- 同时,使用占位符技术优化用户等待体验
# 2、网络层优化
- CDN分发与缓存:
- 使用内容分发网络(CDN)缓存静态资源(如HTML、CSS、JS、图片等),加速用户访问的响应速度,并减轻源服务器的压力
- CDN节点的智能调度可以将用户请求路由到离用户最近的服务器,减少网络延迟
- 就近路由:通过配置智能DNS,根据用户地理位置选择最优的CDN节点,进一步减少延迟
# 3、负载层设计
- 负载均衡(SLB/ELB):
- 使用云端的负载均衡服务(如腾讯云的SLB或阿里云的SLB)
- 配置多区域、全局负载均衡,确保请求被合理分发到多个服务器,减少单点故障
- 反向代理与缓存(Nginx+Keepalived):
- 使用Nginx作为反向代理,结合Keepalived实现高可用性,避免单台Nginx节点失效
- Nginx还可配置缓存机制,缓存部分动态页面或API响应,减少后端服务器压力
- Nginx限流与流量控制:
- 在Nginx层设置请求限流与流量控制规则,针对秒杀活动设置每秒访问限制,避免服务器过载
- 比如每个IP、每个用户账号一秒内只能发起有限次数的请求,防止恶意刷单
# 4、服务层设计
- 动态页面静态化:
- 通过页面静态化技术,将秒杀页面预先生成静态内容,减少实时生成页面的负载
- Redis缓存:
- 使用Redis进行缓存,缓存商品库存、用户会话、热点商品详情等信息,减轻数据库查询压力
- 特别是商品库存可以用Redis原子操作(如
INCR
、DECR
)进行更新,保证高并发下的性能和一致性
- 分布式锁与限流:
- 对于关键操作(如扣减库存、创建订单等),可以使用Redis或ZooKeeper实现分布式锁,避免多台服务器同时操作导致数据异常
- 还可以利用Redis的
setnx
、expire
等操作实现简单高效的限流
# 5、异步任务与消息队列
- 消息队列(RabbitMQ/Kafka)
- 通过消息队列(如RabbitMQ或Kafka)进行异步任务处理
- 将大量的写操作(如订单生成、扣减库存等)放入队列,异步写入数据库,缓解数据库压力
- 在高并发的情况下,消息队列可以起到削峰填谷的作用,确保后端系统处理的稳定性
- 订单状态异步通知:
- 下单成功后,将订单生成状态放入消息队列异步通知用户,避免用户长时间等待响应
# 6、限流与防刷设计
- 漏桶/令牌桶算法:
- 利用漏桶算法或令牌桶算法在应用层进行流量控制,限制用户在秒杀活动中的请求频率,防止恶意流量攻击
- 同时,对于IP地址、账号、设备等可设置访问频次限制
- 验证码与行为验证:
- 在秒杀过程中使用验证码或行为分析(如滑动验证),防止机器人和恶意用户参与秒杀,保障活动的公平性
# 7、数据库层优化
- 避免超卖问题:在秒杀系统中,超卖问题是最关键的难题之一可以使用以下几种方式:
- 乐观锁:基于数据库的版本号机制,在更新库存时检查版本号是否一致,防止多个事务同时修改库存
- 悲观锁:在查询库存时加锁,确保一个时刻只有一个线程能操作库存,防止并发问题
- 分布式事务:通过TCC(Try-Confirm-Cancel)等分布式事务方案保证数据的一致性和准确性
- MySQL主从架构:
- 将MySQL数据库部署为主从结构,主库负责写操作,从库负责读操作,减轻主库的压力,保证高并发下的查询效率
- 主从同步机制可以确保数据的一致性
- 数据库分库分表:
- 水平分库:将用户数据按用户ID、地域等规则分库,减小单个数据库的负载例如,可根据用户ID对多个数据库进行均匀分配
- 垂直分表:将某个大表按时间维度拆分为多张表,例如将订单表按创建时间分成“半年内订单表”、“半年到一年订单表”等
- 热点数据优化:对于热点商品,可以将数据提前加载到内存数据库(如Redis)中,减少数据库查询,提升响应速度
# 8、数据持久化与日志
- 异步日志系统:使用日志收集系统(如ELK、Fluentd)记录秒杀活动中的各类操作日志,并支持实时监控与预警,快速定位和处理问题
- 订单数据持久化:在订单生成后,将订单数据持久化到异步存储(如消息队列+数据库),防止出现丢单情况订单数据可以定期归档,减少活跃数据量
# 9、监控与报警
- 全链路监控:部署Prometheus、Grafana等监控工具,实时监控系统的各个关键节点(如Nginx负载、Redis缓存、数据库性能等),提前发现系统瓶颈
- 日志分析与异常预警:通过日志系统(如ELK或Kibana)对秒杀过程中的请求量、错误率等进行实时分析,一旦出现异常情况(如数据库响应慢、库存扣减失败等)可以及时报警
# 10. 高可用与容灾
- 服务熔断与降级:为了保证秒杀活动的稳定性,可以通过熔断机制(如Hystrix)在高并发或出现问题时自动降级某些服务比如当库存查询压力过大时,返回一个缓存中的静态库存信息,避免频繁查询数据库
- 多活与灾备:将应用部署在多个可用区甚至多地域的数据中心,保证在一个数据中心失效时,流量可以迅速切换到另一个区域,确保系统的高可用性