亲自动手设计一个高并发的秒杀系统

2,158 阅读5分钟

一、需求

  1. 有多款商品,每款商品均100件,每人限每款商品最多购买一件。
  2. 在X月X日 X时X分0秒开启购买。在约定时间之前,只能看到产品页面,购买按钮置灰。

二、活动预估

  1. 预计每种商品数万人参与
  2. 活动开始后半分钟内,预计每种商品收到10W次交易请求,预计总TPS:20W/s
  3. 活动开始半分钟后,预计绝大多数商品已售罄,剩下的商品仍支持秒杀,预计总TPS:2000/s

三、系统现状

  1. 系统可保持长期稳定运行的最大TPS:1000/s
  2. 短时间「1分钟内」系统未拒绝服务的最高TPS:1500/s

四、设计预研

方案一:改造现有系统,微服务系统整体大幅增加TPS

优点:

  1. 大幅增加TPS后,业务系统可直接承载巨量交易请求,应付秒杀需求会更加从容。

缺点:

  1. 秒杀活动次数少,改造成本、风险较大,性价比低
  2. 改造后,系统架构会更加复杂,可维护性降低

方案二:开发新应用,承载该需求;改造现有应用以支持新应用

优点:

  1. 对现有业务系统改造小,成本低。
  2. 使用新应用承载秒杀交易请求,灵活度高,不用过多考虑向后兼容问题。

缺点:

  1. 需要一定程度牺牲用户体验。

结论

基于成本和可行性考虑,采用方案二

五、架构设计

5.1 现有架构设计

  1. 前台应用直接承接用户访问、交易请求,无CDN服务。
  2. 前台应用接收到交易请求后,直接RPC同步请求中台应用
  3. 中台应用受到交易请求后,同步完成创建订单、支付、扣减商品数、完成交易等业务流程
  4. 前台应用接收到中台应用的处理结果,向用户展示交易商品的物流信息。

5.2 最新架构设计

5.2.1 架构设计一览图

秒杀系统架构

5.2.2服务模块设计

1. 前端、客户端随机丢弃交易请求
  1. 根据用户查看商品详情页的次数,预估商品的热门程度,对不同商品设定不同的丢弃比率,设计字段:discard,取值为 [0, 100),作为商品属性。
  2. 前端、客户端,在用户提交交易请求时,生成 [0, 100] 范围内的随机数,discard < 随机数的订单直接丢弃,但向用户展示排队页面,排队10秒后直接显示交易失败。
2. 提供CDN服务
  1. 静态资源均保存在CDN服务中
  2. 前端展示的专门秒杀页面,除了「交易发起」请求外,用户的任何操作均不会请求到公司的微服务业务系统。
3. 开发专门的「秒杀应用」,提供熔断服务
  1. 秒杀应用直接承载前端、客户端的交易请求,授权通过的请求发往前台应用处理,授权拒绝的请求直接拦截,返回交易失败。
  2. 秒杀应用通过配置中心,实时获取最新配置。可配置对交易的丢弃比率,开发同事在秒杀时间段内,调整配置,保证发往业务系统的交易请求,TPS保持在 10000/s 以内。
  3. 秒杀应用无数据库,无状态,水平扩展后可成比例增加吞吐量。
4. 现有业务系统优化吞吐
  1. 前台、中台各应用,通过优化设计进而优化吞吐,有如下优化方式:
    • 采用分库分表等水平拆分方式,横向扩展数据库,此时也可以大幅增加POD数了
    • 静态数据缓存在Redis中,数据从Redis中取,保证不会读取数据库,后台定时任务更新缓存。「保证缓存定时更新且无缓存击穿」
  2. 分库分表策略:
    • 按照商品拆分数据库与应用
    • 按照用户id二次拆分数据库与应用
  3. 经过上述优化,至少可以将中台业务系统的短时间「1分钟内」系统未拒绝服务的最高TPS,由2000/s提升至4000/s
  4. 由于前台应用逻辑较简单,TPS可提升至10000/s,无需再优化。
  5. 由于木桶效应,业务系统整体的短时间「1分钟内」系统未拒绝服务的最高TPS,为4000/s
5. 异步队列
  1. 前台应用效率较高,此处仅优化中台应用即可。
  2. 前台应用将秒杀交易请求均发往 Kafka,中台应用通过 Kafka 消费消息,进行实际业务处理。
  3. 由于业务高峰时间段最多仅有半分钟 ~ 1分钟,中台应用在 2 分钟左右处理完全部交易也可以接受。
  4. Kafka 的 TPS 为数十 W/s,承载前台 5000/s ~ 10000/s 的TPS毫无压力。
  5. 经此优化,业务系统整体的短时间「1分钟内」系统未拒绝服务的最高TPS,可从 4000/s 提升至 10000/s

缺点:极端情况下,交易处理会较为缓慢。

6. 服务降级
  1. 秒杀开始前半小时到秒杀结束后的半小时,这个时间段内,部分服务降级
  2. 时间段内,不展示物流信息、不支持生成及展示发票,保证核心业务系统的稳定