赞
踩
https://blog.csdn.net/weixin_43919497/article/details/119876246
https://blog.csdn.net/weixin_44936189/article/details/116354559
目的就是解决下单操作时流量过大的问题、假设有某个商品商品总数只有一个、而抢他的人有几百万个、那么在秒杀时假设没有限流一秒之内一个服务器突然就受到了百万几的压力、这样服务器很容易就会奔溃挂掉。而削峰限流的目的就是为了防止这种事情的发生保护服务器的安全。
为了承载高并发,就要用到一些技术组合,这里记录下削峰限流组合的方案流程。
下单前先去验证下,目的是交易是为了让有权限的人来交易,而一下子来了1000人,结果只有100人有权限,如果让这1000人都先去交易再看有权限没有,就会很浪费性能。因此可以提前筛选下,让验证通过的直接交易就可以了。
所以现在削减流量的环节就可以放在验证上了,大致流程如下:
用户验证后就会获得一个令牌,有这个令牌就可以交易。
但是令牌的发放量也得有限制。因为有权限的人肯定比可交易量大,所以令牌就限制为可交易量大小。即有10000人,有1000人权限,但库存只有100,就只发放100个令牌去让那1000人抢。
所以现在需要一个大闸(就是一个参数)来限制令牌发放量,每发放一个令牌,大闸就减一,减到0就不发放令牌了。
但如果本来库存就很多,有100万的库存,这时如果发放100万个令牌,并发量也很大。所以这时候就需要一个限流器来限制单机的TPS(比如一个服务器只能承受1万的并发,由于 Nginx 是随机分发流量的,一下子发了5万的请求给它,服务器就会一下就崩了)。
为了完美发挥服务器的性能,限流器的值一般设置在最高并发量左右。但如果这时请求都去交易会产生一个阻塞,那么交易环节就变慢了,这时不理想的。所以就需要一个队列(就是线程池)来缓冲下请求到交易的环节。
那么还能不能在验证前再限制下呢?可以的,我这里就记录了下使用验证码来限制(因为每个人输验证码的速度是不一样的,这样就会分散请求发出的时间来达到平滑流量的目的)。
大题实现逻辑如上图
1. 验证码
验证码模块使用的是easy capcha、这个使用起来很简单就是指定一个路径然后再用一个输出流指定号宽度创建一个specCaptcha对象、最后out就可以了。
2.大闸的实现
大闸是通过redis缓存实现的、他是在缓存中存一个键值、键为promotion:gate:活动id,然后数量是商品数量的5倍。这里本来应该通过后台来是实现的但没有写后台只能通过测试代码来实现。
3.令牌的实现
验证码通过之后就会去获取令牌了
令牌的具体实现如下图
获取令牌后就可以继续下一步了。
4.限流到交易的实现
5. 队列的实现
队列是通过自动注入的spring的线程池实现的、当令牌通过后会通过线程池创建一个线程taskExecutor.submit来去创建订单进行交易。
防刷是防止黄牛以一些方式买走秒杀时的商品然后再以高价卖出去。比较传统的方式有
最先进的方式是通过手机终端来限制
限制每个手机只能买一定数量的商品、但有些黄牛也有很多手机,还是防不住。
项目中通过初始化一个rateLimiter创建了1000个大小的令牌的限流器、限流器底层是采用令牌桶
和漏桶算法
两种算法实现的、本项目使用的是令牌桶
算法。
1. 令牌桶算法
有一个限流器、他会去管理一个叫令牌桶的容器,这个容器容量是有限的、初始化时限流器会给令牌桶加入一定量的令牌,并且初始化完之后会有一个令牌生成器会在间隔固定时间内会生成一些令牌到令牌桶中,当令牌桶满之后会溢出多余的令牌。当用户请求时要先经过限流器获取令牌、当令牌桶中没有令牌时则无法访问、有令牌时会给这个请求一个令牌去访问业务并且令牌桶中的令牌数量会减一。
漏桶算法也有一个桶叫漏桶、这个桶放的是水滴也是有一定容量的。当用户发送请求时就像当于一滴水到限流器中、假设漏桶满了就无法请求、没满就会将这个请求加到漏桶中。漏桶会在一定间隔时间内漏出一定量的水滴也就是处理一定量的请求。
漏桶算法是比较稳的、每次只能处理固定量的请求他的速率是固定的。令牌桶则是可能受到突发情况、突然接收到和令牌桶同样数量的请求、那么服务器就要承受这么大的流量。
所以在实际业务中如果你希望比较平稳的流量访问、就用漏桶。若希望能偶尔承受爆发的流量就使用令牌桶。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。