Redis实现限流

1. 基于Redis的zset数据结构实现滑动窗口限流

我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求。

java 复制代码
public Response limitFlow(){
    Long currentTime = new Date().getTime();
    System.out.println(currentTime);
    if(redisTemplate.hasKey("limit")) {
        Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime -  intervalTime, currentTime).size();  // intervalTime是限流的时间 
        System.out.println(count);
        if (count != null && count > 5) {
            return Response.ok("每分钟最多只能访问5次");
        }
    }
    redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime);
    return Response.ok("访问成功");
}

通过上述代码可以做到滑动窗口的效果,并且能保证每N秒内至多M个请求,缺点就是zset的数据结构会越来越大。实现方式相对也是比较简单的。

3. 基于Redis的list数据结构实现令牌桶限流

令牌桶算法提及到输入速率和输出速率,当输出速率大于输入速率,那么就是超出流量限制了。

我们每访问一次请求的时候,可以从Redis中获取一个令牌,如果拿到令牌了,那就说明没超出限制,而如果拿不到,则结果相反。

java 复制代码
// 定时放令牌
// 10S的速率往令牌桶中添加UUID,只为保证唯一性
@Scheduled(fixedDelay = 10_000,initialDelay = 0)
public void setIntervalTimeTask(){
    redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
}

// 取令牌
public Response limitFlow2(Long id){
    Object result = redisTemplate.opsForList().leftPop("limit_list");
    if(result == null){
        return Response.ok("当前令牌桶中无令牌");
    }
    return Response.ok(articleDescription2);
}
相关推荐
一直都在57215 分钟前
Redis (一)
数据库·redis·缓存
秦jh_34 分钟前
【Redis】客户端使用
数据库·redis·缓存
我真会写代码43 分钟前
Redis核心特性详解:事务、发布订阅与数据删除淘汰策略
java·数据库·redis
IT 行者1 小时前
LangChain4j 集成 Redis 向量存储:我踩过的坑和选型建议
java·人工智能·redis·后端
wenlonglanying1 小时前
nginx 代理 redis
运维·redis·nginx
随风,奔跑2 小时前
Redis
数据库·redis·缓存
TlYf NTLE3 小时前
redis分页查询
数据库·redis·缓存
wangjialelele3 小时前
一文读懂 Redis 持久化与事务
linux·数据库·redis·bootstrap
野犬寒鸦3 小时前
Redis复习记录Day03
服务器·redis·后端·面试·bootstrap·mybatis
曲幽4 小时前
FastAPI里玩转Redis和数据库的正确姿势,别让异步任务把你坑哭了!
redis·python·mysql·fastapi·web·celery·sqlalchemy·task·backgroundtask