秒杀系统设计 demo
业务背景
业务模式
你们挑选选品各大电商平台上畅销和好评的商品进行销售,每个品类不超过 20 个商品,目前做了 10 个品类;
本次 6.18 秒杀选择了 1000 个充电宝,10 台 iPhone 12 作为秒杀商品;
正常的日活大约 100 万用户;
老板要求万无一失。
技术背景
技术团队以 Java 为主,已经落地了微服务架构;
主要渠道是自有的 App(包括 iOS 和 Android)和微信小程序,为了促进用户转化为 App 用户,只有下载 App 才能参加秒杀活动;
目前只有单机房。
业务基本场景
【业务流程图】
【核心流程图】
仅使用 App 登录的用户才显示秒杀商品
进入商品详情页,点击秒杀按钮触发秒杀操作
只有秒杀成功,才会生成订单,进入支付流程
当商品库存为 0 时,秒杀结束
总体架构思路
百万用户规模存储性能估算
秒杀
受限于商品总数量和种类,商品信息数据一共 2 条,分别的库存记录数据也只有两条。
假设所有日活用户均在 0 点时参与秒杀,则信息读取量为 100w × (2+2) = 400w 次/天
订单
由于订单是在秒杀成功后才生成的,故受限制于参与秒杀的商品数量,总共 1010 条
只有秒杀成功的用户才能查看订单,故信息读取量也为 1010/天
支付
订单生成后可进行限时异步支付(如 30 分钟内付款),此步可通过降级、重试、用户侧友好提示等方式进行服务压力分散,故此时信息读取量不是热点
即使同时进行付款,最高写入量也限制于订单的数量,既 1010 次。读取量假设每个秒杀成功的用户会检查 2 次,为 2020 次
存储架构设计
Mysql 主备切换
根据前述分支可知,订单和支付各自的数量均为 1010 条,即使预留 20%的容错设计,数据量也不大,单机即可支持读写。故订单服务和支付服务均直接访问 Mysql
订单和支付属于关联数据,故同样更适合 Mysql 存储
为保障秒杀期间的高可用,采用 Mysql 主备切换模式
RedisCluster
由于秒杀的 TPS 极高,超出单台 Redis 的处理限度,不适用于哨兵模式,故采用 Redis Cluster 进行存储。
为了分散秒杀的 QPS 压力,由于秒杀商品只有两种,商品信息数据量不大,故采用多个节点冗余存储商品信息。
为了分散秒杀的 TPS 压力,且避免因分布式事务增加系统复杂度,将商品库存信息分段存储(sharding)在不同节点上,如 1500 台充电宝的库存信息缓存在节点 1,5011000 台缓存在节点 2。
百万用户规模计算性能估算
秒杀
日活约为 100w 用户,假设全部在 0 点时参与秒杀活动,同时预留 20%的新增用户,故 TPS≈120w
订单
由于订单是在秒杀成功后才生成的,故受限制于参与秒杀的商品数量,TPS≈1010
只有秒杀成功的用户才能查看订单,故 QPS=TPS
支付
订单生成后可进行限时异步支付(如 30 分钟内付款),此步可通过降级、重试、用户侧友好提示等方式进行服务压力分散,故 TPS 和 QPS 均不是热点
即使同时进行付款,最高 TPS 也等于订单的数量,既 1010
负载均衡设计
考虑到目前仅有单机房,采用限流+排队限制 App 端进入的最高 TPS,保护后台服务
采用 Nginx 负载均衡
利用 Kafka 实现排队功能
缓存设计
由于只有 App 端可以参与秒杀,故可采取 App 端缓存
由于成本限制和功能特性,秒杀核心流程不采用 CDN 加速
因为秒杀对于性能要求极高,加之团队已有微服务落地经验,可增加应用内缓存
【五级缓存】
可扩展架构设计
微服务拆分
由于团队有微服务落地经验,故基础设施可复用之前已有的
因为秒杀的压力极大,必须有完善的微服务监控和全链路压测
版权声明: 本文为 InfoQ 作者【Geek_e8bfe4】的原创文章。
原文链接:【http://xie.infoq.cn/article/38c618967ccb46d958f3361f0】。未经作者许可,禁止转载。
评论