当前位置: 首页 > article >正文

基于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();

        }


    }


http://www.kler.cn/a/583406.html

相关文章:

  • 蓝桥杯第三天:2023蓝桥杯省赛 第 1 题
  • Django系列教程(4)——实例项目任务管理小应用
  • 链上权益:基于区块链技术的数字版权管理革命
  • C#+AForge 实现视频录制
  • C#线程上异步执行(this.BeginInvoke)
  • 【CSS3】筑基篇
  • BambuStudio学习笔记:ModelArrange
  • Linux云计算SRE-第十八周
  • 基于OpenCV的车牌识别系统(源码+论文+部署教程)
  • 策略模式和责任链模式的区别
  • Day07 -实例 非http/s数据包抓取工具的使用:科来 wrieshark 封包监听工具
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(33)玲珑宝塔藏珍宝 - 打家劫舍(空间压缩)
  • ubuntu24安装xinference
  • blazemeter工具使用--用于自动生成jmeter脚本并进行性能测试
  • 【使用VGG进行迁移学习:超参数调节与优化技巧】
  • Matlab 双线性插值(二维)
  • 有没有开源的企业网盘,是否适合企业使用?
  • search搜索框功能完善
  • prompt大师高效提示词解析
  • spring boot和spring cloud的区别