太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

秒杀业务分析
正常电子商务流程:

  1. 查询商品
  2. 创建订单
  3. 扣减库存
  4. 更新订单
  5. 付款
  6. 卖家发货
秒杀业务的特性
  1. 低廉价格
  2. 大幅推广
  3. 瞬时售空
  4. 一般是定时上架
  5. 时间短、瞬时并发量高
秒杀技术挑战假设某网站秒杀活动只推出一件商品 , 预计会吸引1万人参加活动 , 也就说最大并发请求数是10000 , 秒杀系统需要面对的技术挑战有:
1、对现有网站业务造成冲击
秒杀活动只是网站营销的一个附加活动 , 这个活动具有时间短 , 并发访问量大的特点 , 如果和网站原有应用部署在一起 , 必然会对现有业务造成冲击 , 稍有不慎可能导致整个网站瘫痪 。
解决方案:将秒杀系统独立部署 , 甚至使用独立域名 , 使其与网站完全隔离 。
2、高并发下的应用、数据库负载
用户在秒杀开始前 , 通过不停刷新浏览器页面以保证不会错过秒杀 , 这些请求如果按照一般的网站应用架构 , 访问应用服务器、连接数据库 , 会对应用服务器和数据库服务器造成负载压力 。
解决方案:重新设计秒杀商品页面 , 不使用网站原来的商品详细页面 , 页面内容静态化 , 用户请求不需要经过应用服务 。
3、突然增加的网络及服务器带宽
假设商品页面大小200K(主要是商品图片大小) , 那么需要的网络和服务器带宽是2G(200K×10000) , 这些网络带宽是因为秒杀活动新增的 , 超过网站平时使用的带宽 。
解决方案:因为秒杀新增的网络带宽 , 必须和运营商重新购买或者租借 。为了减轻网站服务器的压力 , 需要将秒杀商品页面缓存在CDN , 同样需要和CDN服务商临时租借新增的出口带宽 。
4、直接下单
秒杀的游戏规则是到了秒杀才能开始对商品下单购买 , 在此时间点之前 , 只能浏览商品信息 , 不能下单 。而下单页面也是一个普通的URL , 如果得到这个URL , 不用等到秒杀开始就可以下单了 。
解决方案:为了避免用户直接访问下单页面URL , 需要将改URL动态化 , 即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL 。办法是在下单页面URL加入由服务器端生成的随机数作为参数 , 在秒杀开始的时候才能得到 。
5、如何控制秒杀商品页面购买按钮的点亮
购买按钮只有在秒杀开始的时候才能点亮 , 在此之前是灰色的 。如果该页面是动态生成的 , 当然可以在服务器端构造响应页面输出 , 控制该按钮是灰色还是点亮 , 但是为了减轻服务器端负载压力 , 更好地利用CDN、反向代理等性能优化手段 , 该页面被设计为静态页面 , 缓存在CDN、反向代理服务器上 , 甚至用户浏览器上 。秒杀开始时 , 用户刷新页面 , 请求根本不会到达应用服务器 。
解决方案:使用JAVAScript脚本控制 , 在秒杀商品静态页面中加入一个JavaScript文件引用 , 该JavaScript文件中包含秒杀开始标志为否;当秒杀开始的时候生成一个新的JavaScript文件(文件名保持不变 , 只是内容不一样) , 更新秒杀开始标志为是 , 加入下单页面的URL及随机数参数(这个随机数只会产生一个 , 即所有人看到的URL都是同一个 , 服务器端可以用redis这种分布式缓存服务器来保存随机数) , 并被用户浏览器加载 , 控制秒杀商品页面的展示 。这个JavaScript文件的加载可以加上随机版本号(例如xx.js?v=32353823) , 这样就不会被浏览器、CDN和反向代理服务器缓存 。
这个JavaScript文件非常小 , 即使每次浏览器刷新都访问JavaScript文件服务器也不会对服务器集群和网络带宽造成太大压力 。
6、如何只允许第一个提交的订单被发送到订单子系统
由于最终能够成功秒杀到商品的用户只有一个 , 因此需要在用户提交订单时 , 检查是否已经有订单提交 。如果已经有订单提交成功 , 则需要更新 JavaScript文件 , 更新秒杀开始标志为否 , 购买按钮变灰 。事实上 , 由于最终能够成功提交订单的用户只有一个 , 为了减轻下单页面服务器的负载压力 , 可以控制进入下单页面的入口 , 只有少数用户能进入下单页面 , 其他用户直接进入秒杀结束页面 。


推荐阅读