dcddc

西米大人的博客

0%

系统学习秒杀系统

秒杀场景的技术挑战和对应的设计原则

  • 并发高
    • 秒杀的服务、数据库单独部署
    • 上游服务限流
  • 读多写少
    • 使用CDN静态化秒杀商品数据,商品详情页直接访问CDN
  • 超卖问题
    • 库存扣减使用本地缓存+redis分布式缓存
    • redis分段锁机制,提升并发度

秒杀服务后端方案设计

异步方案

  • 处理秒杀请求
    • 验证码校验
    • 通过mq消息队列长度判断是否限流
    • 发mq异步处理秒杀请求
  • 异步处理秒杀请求
    • 业务规则校验
    • 扣减redis缓存中的商品库存
    • 生成token
  • 短轮询秒杀资格
    • 返回token
  • 下单
    • 校验token
      • 过期,回补缓存里的商品库存
      • 未过期,下单成功,删除token

优点:

  • 上游通过mq限流,减轻了下游(应用服务器、redis)压力

缺点:

  • 增加了额外缓存用户token的成本

同步方案

与异步的区别:

  • 不用mq限流,处理秒杀请求时直接减库存,生成token
  • 减库存策略不同,采取本地缓存减库存+redis缓存减库存
    • 异步方案采用mq限流,同步方案使用本地缓存拦截额外的请求,达到限流的效果。二者的本质目的都是减少redis减库存压力

减库存方案优化

本地缓存优化

本地缓存预设库存+buffer,防止服务器在高qps压力下宕机,造成少卖

  • 因为还要redis减库存成功才认为减库存成功,所以加buffer不会造成超卖。不过buffer加的过大起不到本地缓存限流的作用,因此需要折中考虑

redis缓存优化

库存过大时,使用redis存在热点key问题,且减库存的并发度不高

解法是分桶

  • 把大库存分成多个小份,用不同的key表示。在redis额外存储一份商品id和分桶key列表的映射关系
    • 这些Key的哈希值不同,大概率不在Redis的同一个槽位中,避免热点key带来的性能问题
    • 每个redis分桶key可以并发做库存扣减操作,提高减库存的并发度