基于Redis的简单限流

BUCKET_MONITOR:保存过去{timeout}时间内的请求
BUCKET_COUNT:用于记录请求的顺序。每到达一个请求,该计数器+1
BUCKET:保留过去{timeout}时间内的成功请求

            //获取UUID
            String token = UUID.randomUUID().toString();
            long now = System.currentTimeMillis();
            //开启事务
            Transaction transaction = jedis.multi();

            //删除BUCKET_MONITOR中{timeout}时间之前的请求
transaction.zremrangeByScore((BUCKET_MONITOR + point).getBytes(), "-inf".getBytes(), String.valueOf(now - timeout).getBytes());
            //zinterstore的权重因子,使BUCKET中的score为原来的类型(即BUCKET_COUNT)
            ZParams params = new ZParams();
            params.weightsByDouble(1.0, 0.0);
            //计算交集,清除BUCKET中的过时请求,这些请求将不被考虑
            transaction.zinterstore(BUCKET + point, params, BUCKET + point, BUCKET_MONITOR + point);

            //计数器自增,记录到达的请求数
            transaction.incr(BUCKET_COUNT);
            List<Object> results = transaction.exec();
            long counter = (Long) results.get(results.size() - 1);

            //新建一个事务
            transaction = jedis.multi();
            //向两个BUCKET中添加内容,score分别为请求到达的时间和BUCKET_COUNT
            transaction.zadd(BUCKET_MONITOR + point, now, token);
            transaction.zadd(BUCKET + point, counter, token);
            transaction.zrank(BUCKET + point, token);
            results = transaction.exec();
            //获取排名(小->大),判断请求是否取得了信号量(也即是否队伍长度超限)
            long rank = (Long) results.get(results.size() - 1);
            if (rank < limit) {
                return token;
            } else {
                //没有获取到信号量,清理之前放入redis中垃圾数据
                transaction = jedis.multi();
                //Zrem移除刚才加入的score
                transaction.zrem(BUCKET_MONITOR + point, token);
                transaction.zrem(BUCKET + point, token);
                transaction.exec();
            }
        } catch (Exception e) {
            log.error("限流出错" + e.toString());
        }
        return null;
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服...
    私藏馆阅读 4,191评论 0 5
  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 9,882评论 1 14
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,208评论 1 51
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,871评论 1 32
  • 不足的地方请大家多多指正,如有其它没有想到的常问面试题请大家多多评论,一起成长,感谢!~ String可以被继承吗...
    启示录是真的阅读 8,083评论 3 3

友情链接更多精彩内容