Redis基于Redisson的限流和限流算法

限流

限流是在高并发或者某个瞬间高并发时,为了保证系统的稳定性,对超出服务处理能力之外的请求进行拦截,对访问服务的流量进行限制。

常见的限流算法有四种:固定窗口限流算法、滑动窗口限流算法、漏桶限流算法和令牌桶限流算法。

固定窗口限流算法

将每个固定时间设置为每个固定窗口,每个固定窗口只能处理固定数量的请求,如果这个窗口处理了限定的请求数量,之后的请求都不再处理,直到下一个时间窗口。固定窗口限流实现简单,但是会出现流量突刺的问题,假设窗口为1s,请求数量为100,999ms 之前都没有请求来,999ms 的时候来了100个请求都接收了,此时下一个窗口的第1ms 的时候也来了100个请求,这就导致系统在短短2ms 内要处理200个请求,无疑会加重系统负载。

打个比方,有一个面馆,每个小时只能20人吃面,划分9点到10点为一个窗口,10点到11点为一个窗口,假设9点59分59秒来了20人吃面,10点00分01秒来了20人吃面,这就导致两秒钟面馆要做40碗面,压力剧增。

 

滑动窗口限流算法

固定窗口是将时间划分为多个窗口,比如每一小时都是一个固定窗口,9点到10点是一个窗口,10点到11点是一个窗口,每个窗口随着时间变化逐渐变小,所以会出现两个流量突刺的问题。

滑动窗口是将一个小时作为窗口,窗口的大小始终不变,在这个窗口内只能存在20个请求。

打个比方,还是那个面馆,这个面馆是一个滑动窗口,面馆里有20个位置,最大只能容纳20个人同时吃面。假如出现上面的情况,9点59分59秒来了20人,10点00分01秒来了20人,虽然来了40人,但是店里只能容纳20人吃面。后来的20人只能等着或者被拒绝。

漏桶限流算法 

系统处理请求就像是一个往一个漏桶中装水,如果装的水量很大,下面的孔来不及流出去,水就会溢出来。保证系统始终以稳定的速率处理请求,不会出现压力激增的问题。

但是因为始终以恒定的速率处理请求,如果系统有多余的资源,效率比较慢。

令牌桶算法

在漏桶的基础上,加上了令牌的概念,以恒定的速率往桶里加令牌,请求到来的时候先获取令牌,然后被处理,如果处理请求的速率慢于加令牌的速度,桶内始终会有令牌,那么请求来了就能被处理。如果处理速率快于令牌,那么桶里会出现没有令牌的情况,到来的请求就会被拒绝。

打个比方,流水线始终以固定的速率生产配件,配件即为令牌,生产的配件会被放在仓库,仓库就是桶,工厂接到了订单请求会先确认仓库中,如果有配件,就会处理订单,如果没配件了,订单就会被拒绝。

Redisson 实现限流 

github地址:

redisson/redisson: Redisson - Easy Redis Java client and Real-Time Data Platform. Sync/Async/RxJava/Reactive API. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring Cache, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache ... (github.com)

实现主要参考开源地址

 1. 配置依赖

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

2. 创建Redisson配置类

/**
 * Redisson 配置
 */
@Configuration
@EnableCaching
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedissonConfig {

    private String port;

    private String host;

    private Integer database;

    private Integer timeout;
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient(){
        // 1. 创建配置
        Config config = new Config();
        String redisAddress = String.format("redis://%s:%S",host,port);
        //设置redis地址,redis 库,过期时间
        config.useSingleServer().setAddress(redisAddress).setDatabase(database).setTimeout(timeout);
        // 2. 创建Redisson实例
        // Sync and Async API
        return Redisson.create(config);
    }
}

3. 创建限流管理器

@Service
public class RedisLimiterManager {
    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流,令牌桶算法
     * @param key 区分不同的限流器,这里是对应的redis的key
     */
    public void doRateLimit(String key){
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        //每秒执行两个请求,设置速率
        rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS);
        //每个请求到来请求 1 个令牌
        boolean b = rateLimiter.tryAcquire(1);
        if(!b){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"请求频繁,请稍后再试");
        }
    }
}

4. 调用限流管理器即可

//注入管理器
@Resource
    private RedisLimiterManager redisLimiterManager;

//调用
//限流每个用户调用方法的次数
        redisLimiterManager.doRateLimit("genCharByAi:"+userId);

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot整合RedisRedisson可以让我们更方便地使用Redis作为缓存或分布式锁。下面是一个简单的示例,展示了如何在Spring Boot项目中实现这个整合: 1. 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.16.0</version> </dependency> ``` 2. 在application.properties或application.yml中配置Redis连接信息: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 在你的Spring Boot配置类中添加Redisson的配置: ```java @Configuration public class RedissonConfig { @Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer() .setAddress("redis://127.0.0.1:6379"); return Redisson.create(config); } } ``` 4. 在你的业务代码中使用RedisRedisson: ```java @Service public class MyService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private RedissonClient redissonClient; public void put(String key, Object value) { // 使用RedisTemplate操作Redis redisTemplate.opsForValue().set(key, value); // 使用Redisson操作Redis RMap<String, Object> map = redissonClient.getMap("myMap"); map.put(key, value); } public Object get(String key) { // 使用RedisTemplate操作Redis return redisTemplate.opsForValue().get(key); // 使用Redisson操作Redis RMap<String, Object> map = redissonClient.getMap("myMap"); return map.get(key); } } ``` 通过上述步骤,你就成功地将RedisRedisson整合到了你的Spring Boot项目中。可以使用`redisTemplate`来直接操作Redis,也可以使用`redissonClient`来获得更多Redisson提供的功能,例如分布式锁、分布式集合等。希望对你有帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值