With the development of Internet applications, high concurrent access has become an extremely important issue for Internet companies. In order to ensure the stability of the system, we need to restrict access to prevent malicious attacks or excessive access from causing system crashes. Current limiting mechanisms are widely used in Internet applications. Redis, as a popular cache database, also provides distributed current limiting solutions.
The current limiting mechanism of Redis mainly has the following two implementation methods:
1. Current limiting based on the token bucket algorithm
The token bucket algorithm is a commonly used limitation method on the Internet. One of the streaming algorithms, Redis provides a current limiting solution based on the token bucket algorithm. The implementation of this solution is mainly based on Redis's ordered set (zset) and Lua script.
The principle of the token bucket algorithm is a fixed-capacity bucket, into which tokens are put at a certain rate. Each request needs to obtain a token from the bucket before it can be processed. If there is no token in the bucket, the request is rejected.
In Redis, we can use ordered sets (zset) to build token buckets. Each element in the ordered set represents a token, its score represents the arrival time of the token, and the value can be any value. Lua script is used to implement the operation of obtaining the token. The specific implementation code is as follows:
-- 获取令牌 local function acquire_token(key, rate, capacity, now) local current_capacity = redis.call("zcount", key, "-inf", "+inf") local delta_time = 1000 / rate local expected_token = math.floor((now - delta_time * capacity) / delta_time) local available_token = math.min(expected_token - current_capacity, capacity) if available_token > 0 then local members = {} for i = 1, available_token do members[i] = now end redis.call("zadd", key, unpack(members)) end local current_time = now local stop_time = current_time + 1000 local expire_time = stop_time - delta_time * (available_token - 1) local result = redis.call("zrangebyscore", key, "-inf", expire_time) if #result > 0 then redis.call("zrem", key, unpack(result)) return 1 end return 0 end -- 调用获取令牌操作 local result = acquire_token(KEYS[1], ARGV[1], ARGV[2], ARGV[3]) return result
Among them, KEYS[1] represents the current-limiting Key, ARGV[1] represents the rate at which tokens are put in, ARGV[2] represents the bucket capacity, and ARGV[3] represents current time.
2. Current limiting based on funnel algorithm
The funnel algorithm is also a commonly used current limiting algorithm. Its principle is a funnel. Requests flow into the funnel like water. If the funnel is full , it will overflow. In Redis, we can also use ordered sets (zset) and Lua scripts to implement the funnel algorithm.
The funnel algorithm needs to maintain a funnel object to record the time of the last request and the current capacity of the bucket. When a new request comes, the algorithm will calculate the increase in capacity of the funnel based on the difference between the current time and the last request time. If the capacity is less than the maximum capacity of the bucket, the request is allowed to pass and the capacity is reduced; otherwise, the request is rejected.
The specific implementation code is as follows:
-- 获取令牌 local function acquire_token(key, rate, capacity, now) local current_capacity = redis.call("hget", key, "capacity") local last_time = redis.call("hget", key, "last_time") if current_capacity == redis.error_reply or current_capacity == ngx.null then current_capacity = capacity redis.call("hset", key, "capacity", current_capacity) else current_capacity = tonumber(current_capacity) end if last_time == redis.error_reply or last_time == ngx.null then last_time = now redis.call("hset", key, "last_time", last_time) else last_time = tonumber(last_time) end local delta_time = now - last_time local expected_capacity = delta_time * rate / 1000 + current_capacity local actual_capacity = math.min(expected_capacity, capacity) if actual_capacity >= 1 then redis.call("hset", key, "capacity", actual_capacity - 1) redis.call("hset", key, "last_time", now) return 1 end return 0 end -- 调用获取令牌操作 local result = acquire_token(KEYS[1], ARGV[1], ARGV[2], ARGV[3]) return result
Among them, KEYS[1] represents the current limiting Key, ARGV[1] represents the water adding rate of the funnel, ARGV[2] represents the capacity of the funnel, and ARGV [3] represents the current time.
Summary
The distributed current limiting mechanism provided by Redis can effectively control concurrent access and ensure the stability of the system. We can choose the token bucket algorithm or funnel algorithm as the current limiting algorithm according to business needs, and implement it through Redis's ordered set (zset) and Lua script. It should be noted that when applying the current limiting mechanism, the algorithm parameters should be reasonably configured based on specific business scenarios and traffic characteristics to avoid negative impacts on user experience.
The above is the detailed content of Implementation method of distributed current limiting mechanism of Redis. For more information, please follow other related articles on the PHP Chinese website!