Heim >Datenbank >Redis >Implementierungsmethode des verteilten Strombegrenzungsmechanismus von Redis

Implementierungsmethode des verteilten Strombegrenzungsmechanismus von Redis

WBOY
WBOYOriginal
2023-05-11 08:49:351420Durchsuche

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn