The company has a need to send a fixed number of requests per minute to a server other than the LAN, a fixed number of requests, it means that all requests sent by all machines in the cluster are a fixed number, which requires a distributed speed limiter. The first thought was to use the incr method in redis and found an example in the official document of redis.
FUNCTION LIMIT_API_CALL(ip)ts = CURRENT_UNIX_TIME()keyname = ip+":"+tscurrent = GET(keyname)IF current != NULL AND current > 10 THEN ERROR "too many requests per second"ENDIF current == NULL THEN MULTI INCR(keyname, 1) EXPIRE(keyname, 1) EXECELSE INCR(keyname, 1)ENDPERFORM_API_CALL()
However, this script has two disadvantages for me: 1. My speed limiter does not limit the speed of a machine, but the speed of the whole cluster. So after judging the length of the key with the speed limit, there will be a lot of machines executing incr actions 2 company DBAs do not support using things
After reading the implementation of the speed limiter in the document, you can either use things or use Lua scripts (the company does not support Lua because Lua is also transactional, and the company is a sharding redis cluster ), all are denied
It seems that we can only detect the program flow chart for a while. Suppose we can only request 20 requests within 1 s.
Step 1 use the incr command to obtain a value 2 to determine whether the value is 1. If the value is 1, it indicates that this acquisition is the first incr operation after the key value expires. In this operation, you need to set the key timeout time. However, transaction support is not used here. When the program runs to check that the value is 1 and the expire operation is not performed, the program can only request 20 times, therefore, after each value is obtained, perform the remainder operation with 10. If the value is a multiple of 10, the system checks the value. If the timeout time is not set, set 3 to determine whether the value is less than 20. If the value is less than or equal to 20, we believe that the thread has obtained the lock within the specified time. If the value is greater than 20, we think that the lock is not obtained, sleep continues to request the lock after a period of time.
In this way, we have implemented a speed limiter that does not use things and Lua scripts.
If there are any errors or more elegant solutions, please give me more advice.
Note that the TTL key must be detected when the value of 1 in the flowchart is a multiple of 10. Here we can optimize the TTL key detection operation. If the value of 1 is a multiple of 10, the expire key is used directly.
Redis speed limiter design (LUA scripts and things are not used)