当前位置:   article > 正文

RedisTemplate实现令牌桶限流

RedisTemplate实现令牌桶限流

令牌桶

Redisson可以实现很多东西,在Redis的基础上,Redisson做了超多的封装,不仅可以用来实现分布式锁,还可以帮助我们实现令牌桶限流。


Ratelimter主要作用就是可以限制调用接口的次数。主要原理就是调用接口之前,需要拥有指定个令牌,限流器每秒会产生X个令牌放入令牌桶,调用接口需要去令牌桶里面拿令牌。如果令牌被其它请求拿完了,那么自然而然,当前请求就调用不到指定的接口。

RateLimter实现限流

  1. @RestController
  2.     @RequestMapping("/redisTest")
  3.     public class RedisTestController {
  4.  
  5.         @Autowired
  6.         private Redisson redisson;
  7.  
  8.  
  9.         @GetMapping("/Token")
  10.         public String testTokenBucket() {
  11.             RRateLimiter rateLimiter = redisson.getRateLimiter("myRatelimiter");
  12.  
  13.             //最大流速 =每10秒钟产生1个令牌
  14.             rateLimiter.trySetRate(RateType.OVERALL, 1, 10, RateIntervalUnit.SECONDS);
  15.  
  16.             //需要1个令牌
  17.             if (rateLimiter.tryAcquire(1)) {
  18.                 return "令牌桶里面有可使用的令牌";
  19.             }
  20.             return "不好意思,请过十秒钟再来~~~~~~~";
  21.         }
  22.     }

RedisTemplate实现方式:

话不多说直接上代码,如下:

  1. package com.shop.cyshop.commons.service;
  2. /**
  3. * 限流器
  4. *
  5. * @date 2024年04月28日 15:02
  6. */
  7. import com.shop.cyshop.commons.locker.LockService;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.data.redis.core.RedisTemplate;
  11. import org.springframework.stereotype.Service;
  12. import java.util.concurrent.TimeUnit;
  13. @Service
  14. @Slf4j
  15. public class RequestLimitService {
  16. private static final String REQUEST_LIMIT_KEY = "request_limit";
  17. private static final int WINDOW_SIZE_SECONDS = 6; //每六秒一次请求限制
  18. private static final int MAX_REQUESTS = 1;
  19. @Autowired
  20. private RedisTemplate<String, String> redisTemplate;
  21. @Autowired
  22. private LockService lockService;
  23. public boolean isAllowed() {
  24. return lockService.lock(REQUEST_LIMIT_KEY + "::glock", "sys", () -> {
  25. long currentTime = System.currentTimeMillis() / 1000; //10
  26. long windowStart = currentTime - WINDOW_SIZE_SECONDS;//4
  27. // 删除过期的记录
  28. redisTemplate.opsForZSet().removeRangeByScore(REQUEST_LIMIT_KEY, 0, windowStart);
  29. // 获取当前窗口内的请求数量
  30. Long currentRequests = redisTemplate.opsForZSet().count(REQUEST_LIMIT_KEY, windowStart, currentTime);
  31. if (currentRequests != null && currentRequests < MAX_REQUESTS) {
  32. // 增加请求记录
  33. redisTemplate.opsForZSet().add(REQUEST_LIMIT_KEY, String.valueOf(currentTime), currentTime);
  34. // 设置过期时间
  35. redisTemplate.expire(REQUEST_LIMIT_KEY, WINDOW_SIZE_SECONDS, TimeUnit.SECONDS);
  36. return true;
  37. }
  38. return false;
  39. });
  40. }
  41. }

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

闽ICP备14008679号