如何实现高性能的秒杀服务

秒杀在以前曾经在电商中是一个非常热门的话题,但是换个角度去看问题,秒杀问题在很多 业务中都存在,本文从一个综述的方向,给读者介绍秒杀相关的问题和解决方法。

什么是秒杀

网络商家在某一预定的营销活动时间里,大幅度降低活动商品的价格,买家只要在这个时间 里成功拍得此商品,便可以用超低的价格买到原本很昂贵的物品。由于在这个活动中商品的 价格调整幅度很大,几千元商品可以用几十元拍到,或者几百元的商品用1元钱拍到,所以 同时参与活动的人数会很多,这样商家就达到了营销的目的。当然正是由于同时参与人数过 多的原因,甚至在活动正式开始后的一秒钟之内,所有的活动商品就已经被抢购完毕,所以 此活动被称谓秒杀活动。 简单的说,秒杀是网络商家为了提高人气吸引买家而采取的区别 于竞拍方式的一种营销手段。

为什么秒杀那么难

从定义上来看,秒杀看起来并不是很难,它也就是普通的销售商品的过程,并且从定义上看 业务流程甚至要比普通的商品销售要简单。但是秒杀却成了广大产品经理和程序员的心病。 因为秒杀具有以下几个特点:

  1. 定时性
  2. 并发量巨大
  3. 购买数量有限制

因此会引发下面这些问题:

  1. 库存管理
    • 售出商品总量不能超出投放量
    • 一个用户不能够买多个商品
    • 未及时付款的商品重新投放
  2. 并发量大
    • 短时间内大量用户涌入
    • 秒杀软件的刷单
  3. 数据库压力大
    • 大量的数据查询
    • 库存减少和付费事务

如何解决

大方向

  1. 削峰,不管是随机丢弃,还是多层筛选,尽可能减少进入核心业务的用户数
  2. 排队,在秒杀场景下,排队不单单可以减少系统压力,还能保证正确性
  3. 分区,使用分区可以降低一个节点当机带来整体性的损害或者雪崩性的系统不可用
  4. 最终一致,很多时候,不一定要强一致性,只要能保证最后数据的正确,哪怕是手工修 复,都能带来大规模的性能提升

削峰

  1. 产品层面
    • 通过设置秒杀的码,例如说小米的F券等
  2. 技术层面
    • 设置验证码,防止机器人
    • 随机丢弃部分用户,保护核心秒杀系统
    • 使用CDN,将静态资源等提前推送到离用户较近的地方,不占用核心机房的带宽
    • 使用流量保护,限制一个IP在一定时间内对系统的访问

排队

使用消息队列,如RabbitMQ。将可以延后处理的事情,推送到队列中,交给后端的工作工作 者慢慢消化。 但是这地方需要注意以下几点:

  1. 数据的排重,不可以让一件商品卖出去多次
  2. 服务可用性,防止因为单个队列因为压力过大而崩溃导致服务不可能用
  3. 数据安全性,需要队列支持持久化和事务性,防止数据没被处理就被丢弃或因队列崩溃 而导致数据丢失

分区

在秒杀系统中,不能将用户全部都压在单个节点上,所以在一开始就应该做好分区策略,例 如使用根据用户ID进行分区或者随机分区的方法。 当然不单单要做好用户分区,也要做好 系统的分区,例如说在排队阶段,需要使用一致性Hash将相同的数据发到同一个数据队列上, 便于数据的排重。 同时使用分区策略的时候,就代表系统是可以扩张的,当用户量级进一 步扩大的时候,我们可以随时进行扩容。

最终一致性

不管系统设计的多么好,最终一致性还是需要做的,因为

  1. 在大并发的情况下,很难不出现异常节点(概率问题)
  2. 即便所有节点都正常,我们仍需要进行校验(人为出错的概率)
  3. 验证产品的稳定性和正确性(测试和公司信誉问题)

采用最终一致性一般的做法,就是将关键日志收集起来,如用户秒杀到了产品,用户付费了 等信息和最终保存在数据库中的数据进行对比,从而确认系统的正确性。