电商秒杀系统架构设计
一、 设计背景
1.1 业务背景
设计电商创业公司的 618 秒杀系统,业务模式如下
1. 挑选选品各大电商平台上畅销和好评的商品进行销售,每个品类不超过 20 个商品,目前做了 10 个品类
2. 本次 618 秒杀先择了 1000 个充电宝、10 台 iPhone 作为秒杀商品
3. 正常的日活大约 100 万用户
4. 老板要求万无一失
1.2 技术背景
1. 技术团队以 Java 为主,已经落地了微服务架构
2. 主要渠道是自有的 App(包括 IOS 和 Android)和微信小程序,为了促进用户转化为 App 用户,只有下载 App 才能参加秒杀活动
3. 目前只有单机房
二、 业务场景分析
2.1 秒杀活动用户行为约定
1. 秒杀预热阶段,App 用户可以直接预约秒杀,也可在秒杀活动开始后直接参与
2. 微信小程序用户登录后,预约秒杀、或者秒杀活动开始直接参与时,会得到只有 App 用户才能参与秒杀的提示,以及 App 下载、注册链接
3. 每个用户可以多次点击秒杀按钮,但要等提示抢单失败后再恢复按钮的可点击状态
4. 系统为竞争秒杀成功的用户创建订单、提供支付链接,1 分钟内支付成功则下单成功;1 分钟内未支付则废弃订单,该物品重新加入秒杀物品池
5. 秒杀池物品被抢完后,秒杀结束
2.2 业务量分析
1. 用户登录 TPS
平均日活 100w,假设总计 500w 用户参与秒杀,秒杀活动参与用户为 300w 登录时间分布在秒杀前 10 分钟,则登录 TPS:300w/10/60≈5000
考虑到大量预约用户会卡点登录,而不是在 10 分钟内均衡分布,这里估算峰值算作平均值三倍,TPS 峰值算 1.5w
2. App 页面访问量
首页访问 TPS 和登录一致为 1.5w
用户在秒杀过程中可能会频繁刷新秒杀页面,或者退出重进秒杀页面,假定 10%参与秒杀的用户有这个动作,且刷新动作在秒杀开始后的 10 秒内完成:则秒杀物品页面访问 TPS 为:300w/10/10=3w
用户在秒杀活动前后也会浏览其他商品,在等待秒杀的时候会发生更多的浏览,嘉定秒杀前 30 分钟,每个登录用户会浏览 10 种商品,则读取商品信息的 TPS 为:300w *10 /(30*60)= 1.7w/s
3. 秒杀事件
秒杀时间到后,用户同时参与秒杀,每个用户可能请求多次,假设 300w 用户平均每人请求 3 次,所有请求在 10s 内完成,即秒杀事件 TPS:300W*3/10=90w/s
因为只有 App 用户可以参与秒杀,可以在 App 端通过随机码取模等方式,直接过滤掉 95%的请求,则真正到达服务端的 TPS 大约是 5w/s
4. 订单
秒杀活动最终生成订单数为 1010,虽然生成时间不一定在同一秒,直接按照 1010 算则:
订单页面访问 TPS:1010
订单提交 TPS:1010
5. 支付
支付 TPS 和订单量一样:1200
6. 秒杀活动不可以影响正常购物
三、 高可用存储架构设计
3.1 存储性能估算
根据上文业务量分析,对秒杀活动存储性能做如下估算:
1. 登录
300w 用户登录会产生 300w 条记录要存储,每条记录包含用户 ID(4 字节)、登录时间(4 字节)、登录 IP(4 字节),总大小为 300w 条*12=3600w 字节=33M
登录 TPS,按照上文计算:1.5w/s
2. 浏览商城
商城商品共 10 个品类,每个品类不超过 20 个商品,需要 200 条数据,都是现有业务已有数据,无需特别设计
页面访问 TPS,采用秒杀时用户刷新页面造成的访问 TPS:3w/s
3. 秒杀
订单数据:1010 条,量很小,无需针对设计存储,写入 TPS:1010/s
支付数据:1010 条,量很小,无需针对设计存储,写入 TPS:1010/s
秒杀请求:TPS:90w/s
秒杀商品库存信息:2 条数据,下订单成功后会变更数据,写入 TPS=支付 TPS=1010/s;读取 TPS:每次秒杀请求都会触发查询备,但 App 端可以通过随机码等方式直接过滤掉大部分请求,筛选掉大部分请求,比如筛除 95%的请求,剩余 5w 请求进入秒杀队列,即库存量读取 TPS:5w/s
4. 常规购买
秒杀前后用户可能会有超出平时的正常购买行为,需要对商城正常的业务做评估,如果有需要就做扩容,但这不在秒杀架构的设计范围之内。
3.2 存储性能需求汇总
3.3 存储架构设计
使用 MySQL 主备,存储登录信息、商品信息、订单信息和支付信息,其中商品信息的读取会使用缓存架构,后文详述
使用 redis,存储库存数据(后文 Redis 还要使用缓存,会被 redis cluster 替代)
四、 高可用计算架构设计
4.1 计算性能预估
根据上文业务量分析,对秒杀活动计算性能做如下估算:
4.2 业务特性分析
1. 用户量 300w,秒杀活动中对性能的需求主要体现在秒杀事件的 TPS(90w)、页面访问(3w),因为只有一个机房,所以需要使用 F5->Nginx->网关的多级负载均衡
2. 页面访问是典型的读操作,且商品页面除库存信息外,在秒杀期间不会更改,所以非常适合使用缓存,且秒杀只是临时的,可以短时间租用 CDN
3. 到达服务端的秒杀 TPS 为 5w/s,但最后智能有 1010 人成功下单,对 redis 库存的瞬间高并发可以使用消息队列作为缓冲,算法选取漏桶算法,队列长度设置为 100w
4.3 负载均衡架构设计
1. 负载均衡算法选择
App 登录用户都可以参与秒杀,因此将请求发给任意服务器都可以,这里选择“轮询”或者“随机”算法。
2. 业务服务器数量估算
秒杀事件 TPS 为 5w/s,由于秒杀过程中绝大多数请求在读到 redis 库存为 0 的消息后就直接返回用户“秒杀失败”的消息了,只有 1010 个请求会进行下一步的创建订单等操作,这里按照每一个服务器每秒处理 1000 来算,完成 5w/s 的 TPS,需要 50 台服务器,加上一定的预留量,70 台就差不多了
商城页面访问 TPS 3w/s,假设 CDN 可以承载 90%的流量,剩下 TPS 为 3000/s 的请求进入系统,这些请求只有读 redis 缓存的操作,按照每一个服务器每秒处理 1000 来算,完成 3w/s 的 TPS,只需要 3 台服务器,加上一定预留量,5 台就差不多了
4.4 缓存架构设计
redis 作为商品信息的缓存,应对 3000/s 进入系统的页面读取请求,只需要主备或者主从即可,但前面还有库存信息需要存储,分别部署两组 redis 作为缓存和存储比较多余;且领导要求万无一失,库存和缓存又是架构中比较关键的设计,这里选择 redis cluster,缓存和存储都可以复用这个集群
4.5 秒杀请求排队设计
五、 可扩展设计
商城已经落地了微服务架构,秒杀活动暂时不用为可扩展做针对性设计,如有需要,可以作为后续工作来规划。
评论