What are the methods of implementing current limiter in Redis

2023-02-11 15:22:53

<p style="text-align: left;">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&#39;s take a look together.</p><p><br/></p><h3 style="text-align: left;">Method 1: Redis-based setnx operation</h3><p style="text-align: left;">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.</p><p style="text-align: left;">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.</p><p style="text-align: left;">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.</p><p style="text-align: left;">In the specific implementation, you can consider using the interceptor HandlerInterceptor:</p><pre class="brush:csharp; hljs java" style="margin-top: 8px; margin-bottom: 8px; padding: 15px; box-sizing: border-box; overflow-x: auto; background-color: rgb(240, 242, 245); color: rgb(45, 48, 55); font-size: 14px; border: 1px solid rgb(219, 225, 232); border-radius: 4px; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-all; text-align: left;">public&nbsp;class&nbsp;RequestCountInterceptor&nbsp;implements&nbsp;HandlerInterceptor&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;LimitPolicy&nbsp;limitPolicy; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;RequestCountInterceptor(LimitPolicy&nbsp;limitPolicy)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.limitPolicy&nbsp;=&nbsp;limitPolicy; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;preHandle(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response,&nbsp;Object&nbsp;handler)&nbsp;throws&nbsp;Exception&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!limitPolicy.canDo())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p style="text-align: left;">At the same time add a configuration LimitConfiguration:</p><pre class="brush:csharp; hljs java" style="margin-top: 8px; margin-bottom: 8px; padding: 15px; box-sizing: border-box; overflow-x: auto; background-color: rgb(240, 242, 245); color: rgb(45, 48, 55); font-size: 14px; border: 1px solid rgb(219, 225, 232); border-radius: 4px; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-all; text-align: left;">@Configurationpublic&nbsp;class&nbsp;LimitConfiguration&nbsp;implements&nbsp;WebMvcConfigurer&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;addInterceptors(InterceptorRegistry&nbsp;registry)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registry.addInterceptor(new&nbsp;RequestCountInterceptor(new&nbsp;RedisLimit1())).addPathPatterns(&quot;/my/increase&quot;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p style="text-align: left;">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:</p><pre class="brush:csharp; hljs java" style="margin-top: 8px; margin-bottom: 8px; padding: 15px; box-sizing: border-box; overflow-x: auto; background-color: rgb(240, 242, 245); color: rgb(45, 48, 55); font-size: 14px; border: 1px solid rgb(219, 225, 232); border-radius: 4px; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-all; text-align: left;">@RestController@RequestMapping(&quot;my&quot;)public&nbsp;class&nbsp;MyController&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;@RequestMapping(&quot;/increase&quot;) &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;increase()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;i++; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p style="text-align: left;">The specific current limiting logic code is in the RedisLimit1 class:</p><pre class="brush:csharp; hljs java" style="margin-top: 8px; margin-bottom: 8px; padding: 15px; box-sizing: border-box; overflow-x: auto; background-color: rgb(240, 242, 245); color: rgb(45, 48, 55); font-size: 14px; border: 1px solid rgb(219, 225, 232); border-radius: 4px; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-all; text-align: left;">/** *&nbsp;Method&nbsp;1:&nbsp;Redis-based&nbsp;setnx&nbsp;operation */public&nbsp;class&nbsp;RedisLimit1&nbsp;extends&nbsp;LimitPolicy&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setNxExpire(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;boolean&nbsp;setNxExpire()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetParams&nbsp;setParams&nbsp;=&nbsp;new&nbsp;SetParams(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setParams.nx(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setParams.px(TIME); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;result&nbsp;=&nbsp;jedis.set(KEY,&nbsp;COUNT&nbsp;+&nbsp;&quot;&quot;,&nbsp;setParams); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(SUCCESS.equals(result))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;canDo()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(setNxExpire())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;jedis.decrBy(KEY,&nbsp;1)&nbsp;&gt;&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} }public&nbsp;abstract&nbsp;class&nbsp;LimitPolicy&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;int&nbsp;COUNT&nbsp;=&nbsp;10;&nbsp;//10&nbsp;request&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;int&nbsp;TIME=&nbsp;10*1000&nbsp;;&nbsp;//&nbsp;10s&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;String&nbsp;SUCCESS&nbsp;=&nbsp;&quot;OK&quot;; &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;Jedis&nbsp;jedis&nbsp;=&nbsp;new&nbsp;Jedis(); &nbsp;&nbsp;&nbsp;&nbsp;abstract&nbsp;boolean&nbsp;canDo(); }</pre><p style="text-align: left;">One effect achieved in this way is a maximum of 10 requests per second.</p>


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