基于Redis实现限流

限流尽可能在满足需求的情况下越简单越好!

1、基于Redsi的increment方法实现固定窗口限流

  • Redis的increment方法保证并发线程安全

  • 窗口尽可能越小越好(太大可能某一小段时间就打满请求剩下的都拿不到令牌了)

  • 这个原理其实就是用当前时间戳然后除窗口大小 在这个窗口大小的时间内 key都一样

    public class RedisRateLimiter {

    复制代码
      private final StringRedisTemplate redisTemplate;
      // 命令前缀
      private final String key;
    
      private final int rate;
    
      private final int window;
    
      public RedisRateLimiter(StringRedisTemplate redisTemplate, String key, int rate,int window) {
          this.redisTemplate = redisTemplate;
          this.key = key;
          this.rate = rate;
          Assert.isTrue(window > 0 && window <= 60,"窗口只支持分钟内");
          this.window = window;
      }
    
      // 检查并获取令牌
      public boolean acquire() {
          String currentKey = key + "_" + (DateUtil.currentSeconds() / window);
    
          Long currentCount = redisTemplate.opsForValue().increment(currentKey);
    
          redisTemplate.expire(currentKey, window, TimeUnit.SECONDS);
    
          if (currentCount > rate){
              return false;
          }
          return true;
      }
    
    
      public void acquireSleep() {
          int count = 0;
          while (!acquire()){
              ThreadUtil.sleep(1,TimeUnit.SECONDS);
              count++;
              log.info("RedisRateLimiter[{}] try acquire sleep {}",key,count);
          }
      }
    
      public boolean acquireSleep(int waitSecond) {
          int count = 0;
          while (!acquire()){
              if (count >= waitSecond){
                  return false;
              }
              ThreadUtil.sleep(1,TimeUnit.SECONDS);
              count++;
              log.info("RedisRateLimiter[{}] try acquire sleep {}",key,count);
          }
          return true;
      }

    }

使用案例:

下面这个任务是实时请求评论和子评论接口,但是两个接口每分钟不能超过100,所以我们使用限流限制10秒不超过18即可也能满足需求。

复制代码
public class ScCommentRealTimeSyncTask  {
        private RedisRateLimiter rateLimiter;

        @PostConstruct
        public void init(){
            rateLimiter = new
                    RedisRateLimiter(stringRedisTemplate,KAOLA_COMMENT_RATE_KEY,16,10);
        }

        @Scheduled(fixedDelay = 3000)
        public void task(){
            // 请求接口1
            rateLimiter.acquireSleep();
            request1();
            
            //请求接口2
            rateLimiter.acquireSleep();
            request2();

        }


    }
相关推荐
见山是山-见水是水4 分钟前
鸿蒙flutter第三方库适配 - 汇率换算器
redis·flutter·华为·harmonyos
香蕉鼠片7 分钟前
Mysql进阶篇
数据库·mysql·oracle
数厘8 分钟前
2.12 sql 数据插入(INSERT INTO)
数据库·sql·oracle
薛定e的猫咪9 分钟前
2026 年 4 月实测:OpenAI Codex 保姆级教程,从安装到 MCP、Skills 与多智能体协作
前端·数据库·人工智能
wgzrmlrm7410 分钟前
Django怎么优雅发送邮件_Python配置SMTP后端实现异步通知
jvm·数据库·python
014-code12 分钟前
Redis 删除缓存失败怎么办?重试、死信、补偿的工程化方案
数据库·redis·缓存
I love studying!!!13 分钟前
Web应用程序:用户账户
前端·数据库·sqlite
窝子面16 分钟前
NestJs+MongoDB+Deepseek+Langchain实现ai聊天助手
javascript·数据库·人工智能·mongodb
zjshuster18 分钟前
流程引擎(Process Engine)简介
java·数据库·servlet
rannn_11130 分钟前
【Redis|高级篇1】分布式缓存|持久化(RDB、AOF)、主从集群、哨兵、分片集群
java·redis·分布式·后端·缓存