【图解秒杀系列】秒杀技术点——秒杀按钮点亮、削峰
- 秒杀按钮点亮
- 涉及的问题以及解决办法
- 处理流程
- 削峰
- 答题 & 验证码
- 具体流程
- 排队
秒杀按钮点亮
在秒杀场景中,秒杀商品页面是需要处理按钮点亮的逻辑的。在秒杀未开始前,按钮置灰,不可点击;在秒杀开始时,按钮会被点亮,此时用户客户端点击按钮。
涉及的问题以及解决办法
如果页面是由服务端动态生成的,那么这个按钮置灰点亮就很容易控制。但是为了减轻服务器负载压力,我们一般设计把页面静态化并存储到CDN中。因此在生成的这个静态页面中,会加入一个特殊JavaScript,该JavaScript携带了秒杀是否开始的标识,该JavaScript不会被浏览器缓存,每次刷新页面都会请求一次,由于该JavaScript文件的体积很小,因此每次刷新页面都请求一次也不会对服务器造成什么压力。
一开始JavaScript服务器返回的特殊JavaScrip中的秒杀开始标识为未开始。然后有一台Linux服务器,该服务器上面跑着一个定时任务,当秒杀到期时,该服务器向JavaScript服务器集群推送新的特殊JavaScript文件,该文件中的秒杀开始标识为开始。
除此以外,用户有可能会通过F12或其他手段拿到下单的URL,在秒杀未开始前就请求下单的接口。为了解决这种问题,我们的下单接口增加一个随机数参数,下单时要验证服务器上的随机数与请求携带的随机数是否一致,如果不一致则下单失败。在秒杀开始时,Linux服务器会生成随机数并推送给下单服务集群,然后在新生成的JavaScript文件中会携带该随机数。
处理流程
- 浏览器刷新秒杀商品页面,会请求CDN服务器获取静态HTML页面。
- 每次刷新页面,都会请求JavaScript服务器获取特殊JavaScript文件。
- 秒杀开始时,Linux服务器上的定时任务到期,会生成下单URL随机数并推送给下单服务器集群,然后生成新的JavaScript文件并推送给JavaScript服务器,新JavaScript文件的秒杀开始标识为已开始,并且携带下单URL随机数参数。
- 秒杀开始后,浏览器刷新页面,请求获取到最新的JavaScript文件,发现秒杀开始标识为已开始,按钮被点亮。
还有很多秒杀商品页面是有倒计时的,倒计时到期后按钮就会马上点亮,这种就在页面倒计时到期时自动触发请求一次JavaScript文件进行局部刷新即可。
削峰
秒杀场景一般伴随着流量突刺的现象,也就是一瞬间大量并发请求涌入。如果不对这种瞬时大流量做一定的处理,服务器可能会扛不住瞬时的压力。
削峰就是一种处理流量突刺很好的手段,削峰的思想就是通过增加一定的机制或处理步骤,把原先的流量峰值削平,比如把1s内瞬时的大流量均摊到几秒甚至一分钟内,这样服务器就能顺利度过秒杀抢购的这段峰值时期。
答题 & 验证码
答题或者验证码机制是达到削峰效果的一种非常有效的手段。在没有答题或验证码机制的前提下,用户点击按钮,就会触发下单请求,由于用户戳按钮的速度是非常快的,很容易造成流量突刺。
增加了答题或者验证码机制后,每个用户答题或输入验证码的速度都是不一样的,有的快有的慢,这就有效的把不同用户下单的请求在时间上错开了,很好的把一瞬间的请求均摊到一个相对较长的时间范围内,使得服务承受的并发压力大大降低。
具体流程
当用户点击按钮时,会先请求验证码服务获取验证码图片。验证码服务会生成验证码并存入redis,然后根据验证码生成验证码图片返回客户端。
我们可以对生成的验证码进行加密,加密后存入redis的就是一个signature(签名)。
然后用户输入验证码,点击确定按钮,然后浏览器会向后端秒杀系统发起请求,并且请求参数中携带用户输入的验证码。
如果存入redis是加密后的signature值,那么验证时也有以同样的加密方式对用户输入的验证码进行加密后,再与redis中的signature值进行比对。
排队
排队是另一种削峰的手段,我们通过消息队列缓存用户下单的请求,然后迅速响应用户一个中间结果。然后后台的异步服务异步消费mq里的消息进行下单操作,通过这种异步处理的手段,就可以很好的起到削峰填谷的效果。
当后台异步下单成功后,往redis写入下单结果,秒杀服务就可以查询redis得知下单成功与否,然后把下单结果显示到页面上。