淘宝大秒系统设计详解

一些数据大家还记得2013年的小米秒杀吗?三款小米手机各11万台开卖 , 走的都是大秒系统 , 3分钟后成为双十一第一家也是最快破亿的旗舰店 。经过日志统计 , 前端系统双11峰值有效请求约60w以上的QPS  , 而后端cache的集群峰值近2000w/s、单机也近30w/s , 但到真正的写时流量要小很多了 , 当时最高下单减库存tps是红米创造 , 达到1500/s 。
热点隔离秒杀系统设计的第一个原则就是将这种热点数据隔离出来 , 不要让1%的请求影响到另外的99% , 隔离出来后也更方便对这1%的请求做针对性优化 。针对秒杀我们做了多个层次的隔离:

  • 业务隔离 。把秒杀做成一种营销活动 , 卖家要参加秒杀这种营销活动需要单独报名 , 从技术上来说 , 卖家报名后对我们来说就是已知热点 , 当真正开始时我们可以提前做好预热 。
  • 系统隔离 。系统隔离更多是运行时的隔离 , 可以通过分组部署的方式和另外99%分开 。秒杀还申请了单独的域名 , 目的也是让请求落到不同的集群中 。
  • 数据隔离 。秒杀所调用的数据大部分都是热数据 , 比如会启用单独cache集群或MySQL数据库来放热点数据 , 目前也是不想0.01%的数据影响另外99.99% 。
当然实现隔离很有多办法 , 如可以按照用户来区分 , 给不同用户分配不同cookie , 在接入层路由到不同服务接口中;还有在接入层可以对URL的不同Path来设置限流策略等 。服务层通过调用不同的服务接口;数据层可以给数据打上特殊的标来区分 。目的都是把已经识别出来的热点和普通请求区分开来 。
动静分离前面介绍在系统层面上的原则是要做隔离 , 接下去就是要把热点数据进行动静分离 , 这也是解决大流量系统的一个重要原则 。如何给系统做动静分离的静态化改造我以前写过一篇《高访问量系统的静态化架构设计》详细介绍了淘宝商品系统的静态化设计思路 , 感兴趣的可以在《程序员》杂志上找一下 。我们的大秒系统是从商品详情系统发展而来 , 所以本身已经实现了动静分离 , 如图1 。
淘宝大秒系统设计详解

文章插图
 
图1 大秒系统动静分离
除此之外还有如下特点:
  • 把整个页面Cache在用户浏览器
  • 如果强制刷新整个页面 , 也会请求到CDN
  • 实际有效请求只是“刷新抢宝”按钮
 
这样把90%的静态数据缓存在用户端或者CDN上 , 当真正秒杀时用户只需要点击特殊的按钮“刷新抢宝”即可 , 而不需要刷新整个页面 , 这样只向服务端请求很少的有效数据 , 而不需要重复请求大量静态数据 。秒杀的动态数据和普通的详情页面的动态数据相比更少 , 性能也比普通的详情提升3倍以上 。所以“刷新抢宝”这种设计思路很好地解决了不刷新页面就能请求到服务端最新的动态数据 。
基于时间分片削峰熟悉淘宝秒杀的都知道 , 第一版的秒杀系统本身并没有答题功能 , 后面才增加了秒杀答题 , 当然秒杀答题一个很重要的目的是为了防止秒杀器 , 2011年秒杀非常火的时候 , 秒杀器也比较猖獗 , 而没有达到全民参与和营销的目的 , 所以增加的答题来限制秒杀器 。增加答题后 , 下单的时间基本控制在2s后 , 秒杀器的下单比例也下降到5%以下 。新的答题页面如图2 。
淘宝大秒系统设计详解

文章插图
 
图2 秒答题页面
其实增加答题还有一个重要的功能 , 就是把峰值的下单请求给拉长了 , 从以前的1s之内延长到2~10s左右 , 请求峰值基于时间分片了 , 这个时间的分片对服务端处理并发非常重要 , 会减轻很大压力 , 另外由于请求的先后 , 靠后的请求自然也没有库存了 , 也根本到不了最后的下单步骤 , 所以真正的并发写就非常有限了 。其实这种设计思路目前也非常普遍 , 如支付宝的“咻一咻”已及微信的摇一摇 。
除了在前端通过答题在用户端进行流量削峰外 , 在服务端一般通过锁或者队列来控制瞬间请求 。


推荐阅读