怎么样用Redis做一个限流工具

234 阅读2分钟

漏桶算法

漏桶算法是一种简单而常用的限流算法,它的基本思路是在一段时间内,将请求按照一定速率放入固定容量的桶中,如果桶已经满了,那么多余的请求就被丢弃。这个桶类似于一个漏桶,请求就像水一样按照一定的速率流入,当桶满了之后,多余的请求就像水溢出漏桶一样被丢弃。Redis 的自增INCR 刚好可以做这样的漏桶,并且key的过期时间刚好可以作为时间阈值。

实现思路

1.使用 Redis 的 INCR 命令对计数器进行自增操作。

2.判断一定时间内计数器是否超过了阈值。

3.如果超过了阈值,则表示当前请求需要被限流,可以返回错误信息或者直接抛出异常。

4.如果没有超过阈值,则表示当前请求可以被处理,继续执行业务逻辑。

5.在每个请求处理结束后,根据业务需求选择是否需要将计数器进行重置

image.png

代码实现

下面是一个基于 Redis 的简单限流器的 Java 实现:

import redis.clients.jedis.Jedis;

 

public class RedisLimiter {

    private final String key;

    private final int limit;

    private final int timeout;

    public RedisLimiter(String key, int limit, int timeout) {

        this.key = key;

        this.limit = limit;

        this.timeout = timeout;

    }

    public boolean allowRequest(Jedis jedis) {

        // 获取当前时间

        long now = System.currentTimeMillis();

        // 在 Redis 中设置计数器的 key

        String counterKey = String.format("%s:%d", key, now / 1000);

        // 对计数器进行自增操作

        long count = jedis.incr(counterKey);

        // 设置计数器的过期时间

        jedis.expire(counterKey, timeout);

        // 判断计数器是否超过阈值

        if (count > limit) {

            return false;

        }

        return true;

    }

}

这个限流器每秒可以处理 limit 个请求,如果超过了这个阈值,则当前请求需要被限流。该限流器使用 Redis 的 INCR 命令对计数器进行自增操作,并通过设置计数器的过期时间实现自动重置计数器的功能。可以通过以下代码来测试该限流器的功能:

import redis.clients.jedis.Jedis;

public class Main {

    public static void main(String[] args) {

        // 连接 Redis

        Jedis jedis = new Jedis("localhost", 6379);

        // 创建限流器

        RedisLimiter limiter = new RedisLimiter("test-limiter", 10, 1);

        // 模拟处理请求

        for (int i = 1; i <= 15; i++) {

            if (limiter.allowRequest(jedis)) {

                System.out.println("Processing request #" + i);

            } else {

                System.out.println("Request #" + i + " is limited");

            }

        }

        // 关闭 Redis 连接

        jedis.close();

    }

}