当前位置:   article > 正文

Redis基于Redisson的限流和限流算法_redission 限流

redission 限流

限流

限流是在高并发或者某个瞬间高并发时,为了保证系统的稳定性,对超出服务处理能力之外的请求进行拦截,对访问服务的流量进行限制。

常见的限流算法有四种:固定窗口限流算法、滑动窗口限流算法、漏桶限流算法和令牌桶限流算法。

固定窗口限流算法

将每个固定时间设置为每个固定窗口,每个固定窗口只能处理固定数量的请求,如果这个窗口处理了限定的请求数量,之后的请求都不再处理,直到下一个时间窗口。固定窗口限流实现简单,但是会出现流量突刺的问题,假设窗口为1s,请求数量为100,999ms 之前都没有请求来,999ms 的时候来了100个请求都接收了,此时下一个窗口的第1ms 的时候也来了100个请求,这就导致系统在短短2ms 内要处理200个请求,无疑会加重系统负载。

打个比方,有一个面馆,每个小时只能20人吃面,划分9点到10点为一个窗口,10点到11点为一个窗口,假设9点59分59秒来了20人吃面,10点00分01秒来了20人吃面,这就导致两秒钟面馆要做40碗面,压力剧增。

 

滑动窗口限流算法

固定窗口是将时间划分为多个窗口,比如每一小时都是一个固定窗口,9点到10点是一个窗口,10点到11点是一个窗口,每个窗口随着时间变化逐渐变小,所以会出现两个流量突刺的问题。

滑动窗口是将一个小时作为窗口,窗口的大小始终不变,在这个窗口内只能存在20个请求。

打个比方,还是那个面馆,这个面馆是一个滑动窗口,面馆里有20个位置,最大只能容纳20个人同时吃面。假如出现上面的情况,9点59分59秒来了20人,10点00分01秒来了20人,虽然来了40人,但是店里只能容纳20人吃面。后来的20人只能等着或者被拒绝。

漏桶限流算法 

系统处理请求就像是一个往一个漏桶中装水,如果装的水量很大,下面的孔来不及流出去,水就会溢出来。保证系统始终以稳定的速率处理请求,不会出现压力激增的问题。

但是因为始终以恒定的速率处理请求,如果系统有多余的资源,效率比较慢。

令牌桶算法

在漏桶的基础上,加上了令牌的概念,以恒定的速率往桶里加令牌,请求到来的时候先获取令牌,然后被处理,如果处理请求的速率慢于加令牌的速度,桶内始终会有令牌,那么请求来了就能被处理。如果处理速率快于令牌,那么桶里会出现没有令牌的情况,到来的请求就会被拒绝。

打个比方,流水线始终以固定的速率生产配件,配件即为令牌,生产的配件会被放在仓库,仓库就是桶,工厂接到了订单请求会先确认仓库中,如果有配件,就会处理订单,如果没配件了,订单就会被拒绝。

Redisson 实现限流 

github地址:

redisson/redisson: Redisson - Easy Redis Java client and Real-Time Data Platform. Sync/Async/RxJava/Reactive API. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring Cache, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache ... (github.com)

实现主要参考开源地址

 1. 配置依赖

  1. <dependency>
  2. <groupId>org.redisson</groupId>
  3. <artifactId>redisson</artifactId>
  4. <version>3.30.0</version>
  5. </dependency>

2. 创建Redisson配置类

  1. /**
  2. * Redisson 配置
  3. */
  4. @Configuration
  5. @EnableCaching
  6. @ConfigurationProperties(prefix = "spring.redis")
  7. @Data
  8. public class RedissonConfig {
  9. private String port;
  10. private String host;
  11. private Integer database;
  12. private Integer timeout;
  13. @Bean(destroyMethod = "shutdown")
  14. public RedissonClient redissonClient(){
  15. // 1. 创建配置
  16. Config config = new Config();
  17. String redisAddress = String.format("redis://%s:%S",host,port);
  18. //设置redis地址,redis 库,过期时间
  19. config.useSingleServer().setAddress(redisAddress).setDatabase(database).setTimeout(timeout);
  20. // 2. 创建Redisson实例
  21. // Sync and Async API
  22. return Redisson.create(config);
  23. }
  24. }

3. 创建限流管理器

  1. @Service
  2. public class RedisLimiterManager {
  3. @Resource
  4. private RedissonClient redissonClient;
  5. /**
  6. * 限流,令牌桶算法
  7. * @param key 区分不同的限流器,这里是对应的redis的key
  8. */
  9. public void doRateLimit(String key){
  10. RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
  11. //每秒执行两个请求,设置速率
  12. rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS);
  13. //每个请求到来请求 1 个令牌
  14. boolean b = rateLimiter.tryAcquire(1);
  15. if(!b){
  16. throw new BusinessException(ErrorCode.SYSTEM_ERROR,"请求频繁,请稍后再试");
  17. }
  18. }
  19. }

4. 调用限流管理器即可

  1. //注入管理器
  2. @Resource
  3. private RedisLimiterManager redisLimiterManager;
  4. //调用
  5. //限流每个用户调用方法的次数
  6. redisLimiterManager.doRateLimit("genCharByAi:"+userId);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/883871?site
推荐阅读
相关标签
  

闽ICP备14008679号