如何设计一个秒杀系统

总结极客时间专栏《如何设计一个秒杀系统》

极客时间

问题

其实这类高并发问题,总结起来就是两点,并发读并发写。并且在这种情况下,系统还需要做到:

  • 高性能:支持并发读并发写
  • 一致性:保证系统正确,如不发生超卖等
  • 高可用:保证系统在极端条件下的可用性,PlanB 等

原则

  • 数据尽量少:c-s 传输过程中,数据尽量少,减少传输时间
  • 请求数尽量少:减少资源消耗
  • 路径尽量短:请求会经过若干个中间件,经过的中间件应该尽量少,每个节点都可能会挂,最后整体可用性(<1)就是经过的所有节点可用性的乘积
  • 依赖尽量少:指的是业务依赖(优惠券、用户信息等),防止主要服务被其他附属依赖给拖垮掉
  • 不要有单点:单点就是整个系统中最弱的地方,很容易被击垮

动静分离

静态数据

  • 统一 cache 层
  • CDN
  • 代理服务器缓存

动态数据

  • 业务隔离:必须参加活动需要提前报名,服务器对这些热点进行预热
  • 系统隔离:秒杀系统单独部署,落到不同集群当中,避免拖垮其他服务
  • 数据隔离:针对这些热点数据,比如启用单独的 cache 或 MySQL 实例

流量削峰

面对秒杀系统需要承受的海量流量,如果全部落到数据库上,那么数据库将不堪重负,因此可以进行分层的流量削峰:

  • 答题、验证码等,在客户端直接过滤,将流量摊平,而不是瞬时洪峰流量
  • 服务端请求排队,请求到达了不即时返回,而是塞进队列里,FIFO 方式进行处理,然后异步通知客户端(体验不好,用户无法实时收到反馈)
  • 分层校验,保证落到数据库的请求都是有效请求


减库存

减库存是最关键的一个逻辑,需要保证高并发的情况下,不会发生超售。常用的有三种减库存方案:

  • 下单减库存:下单就减库存,会产生非常多无效订单,体验不好。
  • 付款减库存:可能会有用户在付款完成之后,结果提示没库存了。
  • 预扣库存:用户下单后减库存,但是库存只有几分钟有效期,过了有效期就回收库存,体验较好。

PlanB

高可用系统的 PlanB,针对秒杀系统,可以做一些事,比如:

  • 降级:如系统容量到达一点程度之后,关闭一些非核心功能,把有限的资源让给核心功能
  • 限流:在事先进行压力测试时,预估一个最高 QPS,并将其设为阈值,到达这个阈值之后,其他请求扔队列或者直接丢弃
  • 拒绝服务:最坏的情况,达到某个临界点(CPU 90%)直接拒绝服务,保护服务,等负载下降之后恢复,避免被直接长时间拖垮。