Mit der Entwicklung von Internetanwendungen ist der hohe gleichzeitige Zugriff zu einem äußerst wichtigen Thema für Internetunternehmen geworden. Um die Stabilität des Systems zu gewährleisten, müssen wir den Zugriff einschränken, um zu verhindern, dass böswillige Angriffe oder übermäßiger Zugriff zu Systemabstürzen führen. Strombegrenzungsmechanismen werden häufig in Internetanwendungen verwendet. Als beliebte Cache-Datenbank bietet Redis auch verteilte Strombegrenzungslösungen.
Der Strombegrenzungsmechanismus von Redis verfügt hauptsächlich über die folgenden zwei Implementierungsmethoden:
1. Strombegrenzung basierend auf dem Token-Bucket-Algorithmus
Der Token-Bucket-Algorithmus ist einer der im Internet häufig verwendeten Strombegrenzungsalgorithmen Algorithmus basierend auf dem Token-Bucket-Algorithmus zur Strombegrenzung. Die Implementierung dieser Lösung basiert hauptsächlich auf dem geordneten Set (zset) von Redis und dem Lua-Skript.
Das Prinzip des Token-Bucket-Algorithmus ist ein Bucket mit fester Kapazität, in den Token mit einer bestimmten Rate abgelegt werden. Jede Anfrage muss einen Token aus dem Bucket erhalten, bevor sie verarbeitet werden kann. Befindet sich kein Token im Bucket, wird die Anfrage abgelehnt.
In Redis können wir geordnete Mengen (zset) verwenden, um Token-Buckets zu erstellen. Jedes Element in der geordneten Menge stellt einen Token dar, seine Punktzahl stellt die Ankunftszeit des Tokens dar und der Wert kann ein beliebiger Wert sein. Das Lua-Skript wird verwendet, um den Vorgang zum Erhalten des Tokens zu implementieren. Der spezifische Implementierungscode lautet wie folgt:
-- 获取令牌 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
Unter diesen stellt KEYS[1] den strombegrenzenden Schlüssel dar, ARGV[1] stellt die Rate dar, mit der Token eingegeben werden, ARGV[2] stellt die Kapazität des Buckets dar, und ARGV[3] repräsentiert die aktuelle Zeit.
2. Strombegrenzung basierend auf dem Trichteralgorithmus. Sein Prinzip ist ein Trichter, der wie Wasser überläuft. In Redis können wir auch geordnete Mengen (zset) und Lua-Skripte verwenden, um den Trichteralgorithmus zu implementieren.
Der Trichteralgorithmus muss ein Trichterobjekt verwalten, um den Zeitpunkt der letzten Anforderung und die aktuelle Kapazität des Buckets aufzuzeichnen. Wenn eine neue Anfrage eingeht, berechnet der Algorithmus die Erhöhung der Kapazität des Trichters basierend auf der Differenz zwischen der aktuellen Zeit und der Zeit der letzten Anfrage. Wenn die Kapazität geringer ist als die maximale Kapazität des Buckets, wird die Anfrage zugelassen und die Kapazität wird reduziert; andernfalls wird die Anfrage abgelehnt.
Der spezifische Implementierungscode lautet wie folgt:
-- 获取令牌 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
Unter diesen stellt KEYS[1] den aktuellen Begrenzungsschlüssel dar, ARGV[1] stellt die Wasserzugaberate des Trichters dar, ARGV[2] stellt die Kapazität des Trichters dar, und ARGV[3] repräsentiert die aktuelle Zeit.
Zusammenfassung
Der von Redis bereitgestellte verteilte Strombegrenzungsmechanismus kann den gleichzeitigen Zugriff effektiv steuern und die Stabilität des Systems sicherstellen. Wir können den Token-Bucket-Algorithmus oder den Trichteralgorithmus als aktuellen Begrenzungsalgorithmus gemäß den Geschäftsanforderungen auswählen und ihn über den geordneten Satz (zset) von Redis und das Lua-Skript implementieren. Es ist zu beachten, dass bei der Anwendung des aktuellen Begrenzungsmechanismus die Algorithmusparameter angemessen auf der Grundlage spezifischer Geschäftsszenarien und Verkehrsmerkmale konfiguriert werden sollten, um negative Auswirkungen auf die Benutzererfahrung zu vermeiden.
Das obige ist der detaillierte Inhalt vonImplementierungsmethode des verteilten Strombegrenzungsmechanismus von Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!