秒杀架构的解决方案

之前只讨论了秒杀中的关键点之一乐观锁的实现,但是秒杀架构是一个系统工程,今天要把秒杀架构整体思路整理一下。

秒杀基本流程

  • 1.用户提前来到页面,疯狂刷新,等待开始。
  • 2.秒杀时间到,不断点击抢购按钮。
  • 3.用户等到自己的订单显示成功或失败。
  • 4.有些成功的会退单,别人又有机会抢漏。

基本思路框架,分层减少压力

  • 1.用户界面控制、减少压力
  • 2.浏览器缓存、CDN分散压力
  • 3.读写分离Redis,分散压力
  • 4.乐观锁、订单确认写入主从Redis
  • 5.通过Redis消息队列,Mysql数据库异步写入下单内容
  • 6.通过控制模块管理秒杀数据的同步

1.用户界面控制

用户界面是第一道防线,良好的设计可以抵挡90%的无效请求。

  • 在用户点击下单按钮后、得到响应之前,将按钮置灰或者阻挡新请求的发送,避免用户不断点击导致服务器一系列处理压力。
  • 用户点击后,如果服务器压力过大,可以显示等待loading,或弹出请稍等几秒再试。
  • 用户点击过多,弹出”点击过多,请输入验证码”,可以拖延时间。

2.浏览器缓存、CDN

在有效请求发往业务逻辑服务器之前,可以利用浏览器缓存和CDN进行拦截。

  • 将秒杀页面从一般页面独立出来,尽量做成静态的内容缓存到本地,只有动态的内容才发出实际请求。
  • 利用CDN,将图片、JS、CSS等资源文件分散处理,避免请求发往业务逻辑服务器。

3.读写分离Redis

  • 在读写分离服务器对请求进行判断,将大多数的读请求分散到对应Redis服务器上。
  • 数据本身也分为动态数据和静态数据,可以分散到不同服务器。读写分离Redis可以支持60万以上的QPS。

4.乐观锁、订单写入主从Redis

  • 利用Redis的单线程处理特点,使用Lua脚本做乐观锁写入操作。乐观锁可参考之前的文章
  • 将Lua脚本提前缓存在Redis,利用Redis命令直接调用Lua函数,减少网络数据。
  • 写入主Redis后,自动同步到从Redis,用户就可以读到最新的数据。主Redis可以支持10万级别的QPS。

5.通过Redis消息队列,Mysql数据库异步写入下单内容

如果实际写入达到10万,那么Mysql数据库直接写入订单肯定是应付不了的(每秒300~700次读写)

  • 将确认的订单写入Redis消息队列,异步读取、写入Mysql数据库。
  • 用户在写入Mysql数据库之前就可以看到自己的订单已经确认成功,可以进行支付操作了。

6.通过控制模块管理秒杀数据的同步

在秒杀的整个过程中,通过控制模块进行数据同步和流量限制

  • 尽量早的对请求进行验证,比如爬虫检测屏蔽、用户身份权限验证、订单内容是否合法等。
  • 对后台处理数量进行控制,只让部分流量进入后面的流程,如果有订单失败或退订的情况,再多放一些进来,保持一定的访问量,避免业务服务器崩溃。

其他应对高并发的一些方法

  • 可以对热点商品进行垂直分区,专门设立系统,用户感觉不到这种差别。
  • 对物理区域、不同商品分类、Hash分区,在空间上隔离。
  • 分批通知、错峰执行,在时间上隔离。