削峰、限流
削峰限流要解决什么问题呢,要解决OrderController中create(),下单这个方法,也可以称之为前端的接口,下单时流量过大的问题
虽然说用了异步扣减库存,但是承载力是有限的,如果流量过大,服务器撑不住
另外,秒杀商品有限,将有限的人放进来就可以了,不用把所有参与秒杀的人都放进来
那么怎么限制
我们把业务接口叫做交易,怎么解决流量问题呢易之前的验证迁移出来,单独作为一步
为什么只是解决交易的问题,100个库存只放1000个人进来,而且是有权限的进来,他们来了就能交易,因为已经验证过了
现在限制验证环节的流量,通过验证环节来削减流量,而不是在交易环节,因为都已经挤进来了
验证成功了,就能直接交易吗是,还要给用户颁发一个令牌,有这个令牌才可以去交易;在交易环节,就看有没有这个令牌,有令牌可以交易,没有出去
但是验证成功了就直接发令牌吗,100个商品,只需要让进来1000个人就足够了,1000个人入围去抢就可以了,所以要限制令牌的个数;
所以在中间加一个大闸,大闸就是一个参数,每次我们看这个参数,比如说这个商品开放的流量是1000,那么初始化这个大闸就是1000,颁发一个令牌就减一,最终颁发1000个令牌就行了
所以当用户验证通过的时候,需要看大闸有没有余量,有就颁发令牌,没有退出
有了令牌就能交易吗是,因为有可能商品很多,那么大闸也很多,所以大闸相当于不能起到限流的作用了,因为基本上人人都会得到一个令牌;这个时候,就得想别的办法r> 所以需要去限流,避免单机挂掉,所以需要加限流器,限制单机的TPS(每秒处理多少请求);
那么有了限流器就可以了吗见得,因为限流器限制的流量肯定是按单机比较高的值来限制,比如服务器承载力最大是10000,限流器就写10000甚至多一点,因为想让服务器发挥最大能耗,所以往往写的是服务器接近极限的值;
有可能某些线程由于某些原因阻塞,被卡住了,可能交易环节就变慢了
为了让交易环节有一个缓冲,所以加了一个队列来处理,队列就是线程池,里面有多个线程;超过线程池的承载能力,还有等待队列可以等待;
本来交易环节是单线程处理,现在相当于提交给线程池,多线程处理,线程池处理能力肯定更强,可以复用一些线程,可以利用CPU多核的优势,并发处理,把单线程处理的瓶颈拓宽了
上面都是发送请求以后做的限制,那么能不能在请求之前做限制在申请令牌之前,加验证码,可以平滑流量,因为秒杀的时候,很多人都在点下单的按钮,压力很大;所以加上验证码,要求输入验证码,输入验证码需要几秒钟,所以我们就实现了把一秒1000万的流量平滑到三五秒
漏桶算法
有一个漏桶,桶中装的是水滴,比如这个桶容量是100,那么就是装100滴水;漏桶直接对接业务组件;
漏桶关键是:
1.每秒会漏出若干滴水,漏出的水给业务组件,10滴水就是10个业务请求,不管现在桶中有多少滴水,每秒我只漏10滴水给业务组件,保证业务组件每秒只能处理10个业务请求
2.注水时水满则溢
客户端去访问限流器的时候,一个请求认为是一滴水,限流器尝试往桶中加水,桶的容量是有限制的,如果满了,拒绝请求;如果没有满,就加入一滴水;加进去的水不是立刻给业务组件,桶和业务组件的关系永远都是每秒出十滴水,没有到整秒,不会被处理,可能先到的还会先处理
下单的时候锁库存,不是付款的时候锁库存,而下单时候锁库存有可能就会发生少卖
那么怎么解决用延时队列来解决,下单这一刻,可以把这个处理加到延时队列里,比如过半个小时再消费一下,消费的时候去检查是否进行了付款,付款就移除队列,没有付款就把订单作废,然后移除队列
延时队列可以有两种实现方式:
第一种redis的数据类型,zset,有序集合,相当于一个简单的消息队列;
生产者,下单的时候,往zset中存数据,也就是订单信息,将时间来当做集合对象的分数;消费者定期去看时间最早的订单,检查是否到时了(定时器驱动),到时间了进行处理
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!