RedisTemplate实现令牌桶限流

令牌桶

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

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

RateLimter实现限流

java 复制代码
@RestController
    @RequestMapping("/redisTest")
    public class RedisTestController {
 
        @Autowired
        private Redisson redisson;
 
 
        @GetMapping("/Token")
        public String testTokenBucket() {
            RRateLimiter rateLimiter = redisson.getRateLimiter("myRatelimiter");
 
            //最大流速 =每10秒钟产生1个令牌
            rateLimiter.trySetRate(RateType.OVERALL, 1, 10, RateIntervalUnit.SECONDS);
 
            //需要1个令牌
            if (rateLimiter.tryAcquire(1)) {
                return "令牌桶里面有可使用的令牌";
            }
            return "不好意思,请过十秒钟再来~~~~~~~";
        }
    }

RedisTemplate实现方式:

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

java 复制代码
package com.shop.cyshop.commons.service;

/**
 * 限流器
 *
 * @date 2024年04月28日 15:02
 */

import com.shop.cyshop.commons.locker.LockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class RequestLimitService {

    private static final String REQUEST_LIMIT_KEY = "request_limit";
    private static final int WINDOW_SIZE_SECONDS = 6; //每六秒一次请求限制
    private static final int MAX_REQUESTS = 1;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private LockService lockService;

    public boolean isAllowed() {
        return lockService.lock(REQUEST_LIMIT_KEY + "::glock", "sys", () -> {
            long currentTime = System.currentTimeMillis() / 1000; //10
            long windowStart = currentTime - WINDOW_SIZE_SECONDS;//4

            // 删除过期的记录
            redisTemplate.opsForZSet().removeRangeByScore(REQUEST_LIMIT_KEY, 0, windowStart);

        
            // 获取当前窗口内的请求数量
            Long currentRequests = redisTemplate.opsForZSet().count(REQUEST_LIMIT_KEY, windowStart, currentTime);

            if (currentRequests != null && currentRequests < MAX_REQUESTS) {
                // 增加请求记录
                redisTemplate.opsForZSet().add(REQUEST_LIMIT_KEY, String.valueOf(currentTime), currentTime);
                // 设置过期时间
                redisTemplate.expire(REQUEST_LIMIT_KEY, WINDOW_SIZE_SECONDS, TimeUnit.SECONDS);
                return true;
            }
            return false;
        });
    }
}
相关推荐
CHEN5_022 小时前
【CouponHub开发记录】SpringAop和分布式锁进行自定义注解实现防止重复提交
java·分布式·spring·项目
编啊编程啊程2 小时前
Netty从0到1系列之Selector
java·spring boot·spring cloud·java-ee·kafka·maven·nio
angushine3 小时前
Spring Boot 工程启动时自动执行任务方法
java·spring boot·后端
冷雨夜中漫步4 小时前
ClickHouse常见问题——ClickHouseKeeper配置listen_host后不生效
java·数据库·clickhouse
野犬寒鸦5 小时前
力扣hot100:缺失的第一个正数(哈希思想)(41)
java·数据结构·后端·算法·leetcode·哈希算法
重生成为编程大王6 小时前
Java中使用JSONUtil处理JSON数据:从前端到后端的完美转换
java·后端·json
天若有情6736 小时前
《JAVA EE企业级应用开发》第一课笔记
java·笔记·后端·java-ee·javaee
豆沙沙包?7 小时前
2025年- H109-Lc1493. 删掉一个元素以后全为 1 的最长子数组(双指针)--Java版
java
Doris_LMS7 小时前
Git在idea中的实战使用经验(一)
java·git·gitlab·idea
04Koi.8 小时前
面经分享--华为Java一面
java·开发语言