如何设计秒杀系统?

秒杀本身一个促销活动,其本意在于通过限量低价商品来吸引大量流量的营销推广

秒杀的商品不一定是低价的,还有可能是热门限量商品,比如某些时间段的显卡、ps5等

基本秒杀形式就是保证只有发起请求最早的少数用户能够购买到指定商品

主要技术挑战就是瞬间高并发压力

秒杀大概流程如下

  1. 用户进入秒杀页面
  2. 用户发起秒杀请求
  3. 反向代理到相应服务
  4. 校验并查询库存
  5. 锁定库存
  6. 支付后购买成功

如何保障瞬间高读写压力下的正常功能运转?

主要的设计思路就是尽可能在最前面的环节拦截无效请求以及尽可能不影响其他基本模块功能使用

前端方法

  1. 前端页面缓存:可以预知的是秒杀页面将会收到第一波压力,因此可以事先采用CDN缓存起来
  2. 前端超时关闭秒杀请求:前端可以根据后端返回秒杀状态或者秒杀时间关闭秒杀按钮,来减少不必要秒杀请求
  3. 前端限制短时间的请求次数

业务方法

  1. 提前尽可能估计流量规模:可以通过提前预约、商品收藏数量、平台用户规模等等预估大概流量

  2. 缩小秒杀用户群体:比如要求只有会员、预约过的才能进行秒杀

    甚至可以截断用户请求量,然后随机选择秒杀成功用户。比如100个商品库存量,仅接受前300用户请求,然后在这300中随机选择

  3. 加机器,加人:如有必要,可以加机器加人提前应对

后端方法

  1. 缓存加速:通过缓存判断是否存在库存,若不存在则直接返回

    甚至可以直接记录访问量,当访问量达到一定数量,也全部拒绝

    一般来说,缓存比如redis具有超强的处理能力,再加上诸多之前环节相关措施一般不会给予redis太多压力,实在不行大不了上redis主从,并通过lua脚本原子占用库存

  2. 定义请求队列:确保同时秒杀的用户最多队列大小

  3. 秒杀模块解耦:可以把秒杀模块分为两部分,一部分为库存锁定部分,仅仅只是锁定库存,还没有实际购买完成;另一部为实际支付发货部分。那么可以通过诸如消息队列等方法解耦两部分,避免秒杀功能影响实际支付发货的基本功能使用

  4. 异步处理:为了充分利用服务器资源处理秒杀,可以异步处理一些非一定要求同步的流程。比如说发送秒杀成功的短信、还可以是与秒杀解耦的订单模块

  5. 做好熔断降级准备:如果真的出现秒杀模块无法支撑的情况,那么就立即降级甚至熔断,防止影响其他基本功能使用

如何防止超卖?

  • 库存修改加锁:对库存修改加锁

    先扣除缓存库存,然后加锁预扣数据库库存

  • 库存分区加锁,将库存分成多份,每一份加锁。能够降低一些锁粒度,并且能做到地域、用户群等的均匀发布

  • 事后补偿:发现超卖之后给予用户补偿。可作为补充措施,最好不要用于主要措施,除非确定基本不会超卖

  • 数量冗余:若本意是用于营销,那么超卖或者少卖一些又何妨。比如说计划是秒杀100份,但是实际准备120份,通过冗余来解决超卖问题。

  • 延时反馈:不即时反馈是否秒杀成功,而是在一段时间后反馈给用户。

    降低了用户秒杀体验

如果存在大量秒杀成功却不购买怎么办?

  • 尽量事先排除非真实用户

  • 重新释放秒杀商品

    能让真正的用户享受到实惠,真正卖出商品

    捡漏感本身也是一种营销,甚至比秒杀更为持久广泛

  • 秒杀库存仍然扣除

    仅仅只是一个促销活动,是不是真的买到了并不关心

  • 检查是否是恶意攻击

如何防止作弊?

  • 动态url:对url进行加密,后台对url校验后才能继续秒杀
  • 限制请求速度:设定一个人类无法达到的时间,如果在该时间之前请求,那么就直接返回失败
  • 人为防止作弊:如果事后发现有用户存在作弊,则做相应处理。可作为补充措施
  • 限制ip、用户请求数:如果一定时间内请求次数太多,则直接返回错误
  • 验证码:验证码能屏蔽或者延缓大部分非人类发起的请求,不足之处在于会降低一些用户体验

Ref

  1. https://mp.weixin.qq.com/s/RXPZiKo-489rDTPfDAGAVw
  2. https://cloud.tencent.com/developer/article/1520361

你可能感兴趣的:(哲学与架构,java)