基于Redission的令牌桶限流,简单统一复用

本文介绍了如何在SpringBoot项目中引入Redisson库,配置连接参数,并利用其内置的RateLimiter实现限流功能。通过设置限流类型、速率和时间间隔,确保接口访问频率控制。Redisson底层利用Redis的String和ZSet数据结构实现高效限流算法。
摘要由CSDN通过智能技术生成

引入依赖

   <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.21.3</version>
    </dependency>

进行config配置

import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Data
@ConfigurationProperties(prefix = "spring.redis")
@Configuration
public class RedissonConfig {
    private Integer database;
    private String host;
    private Integer port;
    private String password;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
                .setDatabase(database)
                .setAddress("redis://" + host + ":" + port)
                .setPassword(password);
        RedissonClient redisson = Redisson.create();
        return redisson;
    }
}

定义限流规则

package com.yupi.springbootinit.mapper;

import com.yupi.springbootinit.exception.ThrowUtils;
import com.yupi.springbootinit.common.ErrorCode;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流操作
     *
     * @param key 区分不同的限流器,比如不同的用户 id 应该分别统计
     */
    public void doRateLimit(String key) {
        // 创建一个限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 每秒最多访问 2 次
        // 参数1 type:限流类型,可以是自定义的任何类型,用于区分不同的限流策略。
        // 参数2 rate:限流速率,即单位时间内允许通过的请求数量。
        // 参数3 rateInterval:限流时间间隔,即限流速率的计算周期长度。
        // 参数4 unit:限流时间间隔单位,可以是秒、毫秒等。
        rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
        // 每当一个操作来了后,请求一个令牌
        boolean canOp = rateLimiter.tryAcquire(1);
        ThrowUtils.throwIf(!canOp, ErrorCode.OPERATION_ERROR);
    }
}

设置限流器的限流参数

第一个参数为限流类型:整体速率限制,表示所有请求共同享用一个速率的限制。

第二个参数为限流速率,我们设置的为2,就是单位时间内允许通过的请求数量为2,

第三个自然就是限流的时间单位。所以整体允许请求一秒两次。然后再通过限流器对象去获取令牌,如果能拿到返回true执行后面业务逻辑,如果拿不到返回false就停止后面代码执行,响应给前端系统错误

在需要限流的接口处,进入业务逻辑之前,引入该方法就可以实现限流。

不难看出我们其实没有太多操作,因为redission底层已经封装好了。内部大概思路

  1. 使用Redis的String类型存储当前令牌数量,用ZSet(有序集合)存储令牌的过期时间和令牌标识。
  2. Lua脚本首先获取当前令牌数量和相应的限流参数,在令牌桶中查询是否有可用的令牌(未过期)。
  3. 如果有可用的令牌,则分配令牌并更新令牌桶信息;如果没有足够的令牌,则请求被限流。
  4. 最后,更新令牌桶的过期时间,保证令牌桶中的令牌能够定时清理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值