What are the methods of implementing current limiter in Redis

02-11-2023

This article mainly introduces the relevant knowledge of the method of Redis to realize the current limiter. The content is detailed and easy to understand, the operation is simple and fast, and has certain reference value. Which articles will be rewarding, let's take a look together.


Method 1: Redis-based setnx operation

When we use Redis distributed locks, we all know that we rely on setnx instructions , during the operation of CAS (Compare and swap), at the same time set the expiration practice (expire) for the specified key, the main purpose of our current limit is to have and only N number of requests can access within a unit time My code program. So relying on setnx can easily do this function.

For example, we need to limit 20 requests within 10 seconds, then we can set the expiration time to 10 when setnx, and when the number of setnx requests reaches 20, the current limiting effect is achieved. The code is relatively simple and will not be displayed.

Of course, there are many disadvantages of this approach. For example, when counting 1-10 seconds, it is impossible to count within 2-11 seconds. If we need to count M requests within N seconds, then our Redis needs to keep N keys and so on.

In the specific implementation, you can consider using the interceptor HandlerInterceptor:

public class RequestCountInterceptor implements HandlerInterceptor {

    private LimitPolicy limitPolicy;

    public RequestCountInterceptor(LimitPolicy limitPolicy) {
        this.limitPolicy = limitPolicy;
    }

    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!limitPolicy.canDo()) {
            return false;
        }
        return true;
    }
}

At the same time add a configuration LimitConfiguration:

@Configurationpublic class LimitConfiguration implements WebMvcConfigurer {
    @Override    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestCountInterceptor(new RedisLimit1())).addPathPatterns("/my/increase");
    }
}

In this way, each time before the /my/increase request reaches the Controller, the current limit is carried out according to the policy RedisLimit1, and the code in the original Controller does not need to be modified:

@RestController@RequestMapping("my")public class MyController {
    int i = 0;
    @RequestMapping("/increase")
    public int increase() {
        return i++;
    }
}

The specific current limiting logic code is in the RedisLimit1 class:

/**
* Method 1: Redis-based setnx operation
*/public class RedisLimit1 extends LimitPolicy {

    static {
        setNxExpire();
    }

    private static boolean setNxExpire() {
        SetParams setParams = new SetParams();
        setParams.nx();
        setParams.px(TIME);
        String result = jedis.set(KEY, COUNT + "", setParams);


        if (SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

    @Override    public boolean canDo() {

        if (setNxExpire()) {
            //           return true;
        } else {
            //         return jedis.decrBy(KEY, 1) > 0;
        }
    }
}public abstract class LimitPolicy {
    public static final int COUNT = 10; //10 request    public static final int TIME= 10*1000 ; // 10s    public static final String SUCCESS = "OK";
    static Jedis jedis = new Jedis();
    abstract boolean canDo();
}

One effect achieved in this way is a maximum of 10 requests per second.

Copyright Description:No reproduction without permission。

Knowledge sharing community for developers。

Let more developers benefit from it。

Help developers share knowledge through the Internet。

Follow us

Recommended reading

high perspicacity