秒杀业务流程
(1)商户创建秒杀活动,设定秒杀时间段,选择本次活动的商品,设置折扣、库存等;
(2)用户APP端在活动即将开始时会看到秒杀活动列表,点击活动可以看到商品列表,点击商品可以查看秒杀商品详情;
(3)商品详情页用户点击立即抢购;
(4)如果库存充足,则创建订单成功;否则秒杀失败
(5)提交订单后超时未支付,系统会自动关闭订单,回滚库存。
秒杀业务的特性
(1)低廉价格;
(2)大幅推广;
(3)瞬时售空;
(4)一般是定时上架;
(5)时间短、瞬时并发量高;
前端层面
前端优化(前端按钮点击频率限制、限制用户维度访问频率、url加密防暴露、限制商品维度访问频率、验证码机制、页面静态化CDN等)
服务层面
1.nginx限流(nginx配置limit_conn_zone限制同一ip的访问速率)
2.负载均衡
3.服务器硬件升级
4.web服务器限流:MQ(削峰处理)、限流算法(如RateLimiter)、秒杀接口url使用token机制或者加密放暴露(秒杀接口url是可变的)
5.服务降级、熔断(为了保证秒杀系统的高可用性,必须要对系统进行兜底处理,以便遇到极端的情况系统依然能够运转,通常的做法有服务降级、服务限流、拒绝请求等方式处理)
网络
秒杀前要和网络运营商、CDN 服务商提前申请带宽。
利用缓存
秒杀的业务特点是读多写少,一个秒杀商品只有10个,可能有10w个人来抢,最终只有10个用户会产生写操作,其它请求都是查询库存,非常适合利用缓存优化。
缓存这块我们选用redis,redis基于内存,内存的读写速度非常快;同时redis内部是单线程操作,省去了很多上下文切换线程的时间。redis采用多路复用技术,非阻塞式IO,可以抗住高达百万级的并发量。
业务:在活动开始前,我们可以配置循环定时任务,将秒杀活动、秒杀商品相关信息全部缓存到redis中,可以根据活动信息,设置缓存的失效时间。前端秒杀活动、商品详情等数据的获取,全部走redis。
排队下单
利用redis进行排队抢单,记录排队数据。秒杀请求到后端后,不立即走创建订单逻辑,先通过redis校验排队、库存信息,校验通过后将秒杀请求缓存到redis。
业务:用户发送确认订单请求时,首先校验该用户是否是否已经排队,排队信息从redis中获取,如果已经排队下单,直接返回; 否则继续走确认订单的业务逻辑。
削峰处理
业务:通过消息队列削峰,秒杀请求不直接生成订单,先存入消息队列,可以写一个消息监听器,平缓消费秒杀请求数据,减轻数据库并发量。
拒绝请求
如果服务降级、服务限流都不能解决问题,最后的兜底,那就是直接拒绝用户请求,比如直接给用户返回 “服务器繁忙,请稍后再试”等提示文案。只会发生在服务器负载过载时会启动,因此只会发生短暂不可用时刻,由于此时服务依然还在稳定运行中,等负载下降时,可以快速恢复正常服务。
总结
1.如何避免超卖?如果在 redis 中扣减库存,可以利用 decr 命令扣减库存,decr 是原子操作,在分布式环境下也不会有并发问题,decr 扣减库存后,判断返回值,如果返回值小于 0,扣减库存失败,秒杀也就失败了;如果在数据库中扣减库存可以在 where 后面加上库存大于 0 的条件,来避免库存被减成负值。这样就可以避免超卖情况发生了。
2.接口防刷 在网关层对下单等接口按 userID 限流,token机制使接口url不固定。
3.多个账号,不同IP发送不同请求(可以结合风控系统)
所谓道高一尺,魔高一丈。有进攻,就会有防守,永不休止。有些“工作室”,发现你对单机IP请求频率有控制之后,他们也针对这种场景,想出了他们的“新进攻方案”,就是不断改变IP。
有同学会好奇,这些随机IP服务怎么来的。有一些是某些机构自己占据一批独立IP,然后做成一个随机代理IP的服务,有偿提供给这些“工作室”使用。还有一些更为黑暗一点的,就是通过木马黑掉普通用户的电脑,这个木马也不破坏用户电脑的正常运作,只做一件事情,就是转发IP包,普通用户的电脑被变成了IP代理出口。通过这种做法,黑客就拿到了大量的独立IP,然后搭建为随机IP服务,就是为了挣钱。
应对方案:
说实话,这种场景下的请求,和真实用户的行为,已经基本相同了,想做分辨很困难。再做进一步的限制很容易“误伤“真实用户,这个时候,通常只能通过设置业务门槛高来限制这种请求了,或者通过账号行为的”数据挖掘“来提前清理掉它们。
僵尸账号也还是有一些共同特征的,例如账号很可能属于同一个号码段甚至是连号的,活跃度不高,等级低,资料不全等等。根据这些特点,适当设置参与门槛,例如限制参与秒杀的账号等级。通过这些业务手段,也是可以过滤掉一些僵尸号。
4.多个账号,一次性发送多个请求
应对方案:
可以通过检测指定机器IP请求频率就可以解决,如果发现某个IP请求频率很高,可以给它弹出一个验证码或者直接禁止它的请求
5.如何控制秒杀商品页面购买按钮的点亮
倒计时:前端时间需要从服务器获取,以免用户修改本机时间
6.网关层除了对 userID 做限流外,还要做整体限流。在实际访问量超过预估访问量时,整体限流可以起到保护作用,避免系统被压垮。
7.防止重复下单,按 userID 限流已经起到了防止重复下单的作用。假如限制同一个用户 10 分钟能下一次单,一般情况下 10 分钟内,商品早已经被抢光了,用户也就没有再次下单的机会了。
8.可以在网关层上面再加一层防火墙或者高防服务,来防御 DDos 等分布式网络攻击。