Maison  >  Article  >  base de données  >  Méthode de mise en œuvre du mécanisme de limitation de courant distribué de Redis

Méthode de mise en œuvre du mécanisme de limitation de courant distribué de Redis

WBOY
WBOYoriginal
2023-05-11 08:49:351280parcourir

Avec le développement des applications Internet, l'accès simultané élevé est devenu un enjeu extrêmement important pour les entreprises Internet. Afin de garantir la stabilité du système, nous devons restreindre l'accès pour éviter que des attaques malveillantes ou un accès excessif ne provoquent des pannes du système. Les mécanismes de limitation de courant sont largement utilisés dans les applications Internet. Redis, en tant que base de données de cache populaire, fournit également des solutions de limitation de courant distribuées.

Le mécanisme de limitation actuel de Redis comporte principalement les deux méthodes d'implémentation suivantes :

1 Limitation de courant basée sur l'algorithme du bucket de jetons

Token bucket. L'algorithme est l'un des algorithmes de limitation de courant couramment utilisés sur Internet. Redis fournit une solution de limitation de courant basée sur l'algorithme du compartiment à jetons. L'implémentation de cette solution repose principalement sur l'ensemble ordonné (zset) et le script Lua de Redis.

Le principe de l'algorithme du token bucket est un bucket à capacité fixe, dans lequel les tokens sont placés à un certain rythme. Chaque requête doit obtenir un token du bucket avant de pouvoir être traitée. S'il n'y a aucun jeton dans le bucket, la demande est rejetée.

Dans Redis, nous pouvons utiliser des ensembles ordonnés (zset) pour créer des buckets de jetons. Chaque élément de l'ensemble ordonné représente un jeton, son score représente l'heure d'arrivée du jeton et la valeur peut être n'importe quelle valeur. Le script Lua est utilisé pour mettre en œuvre l'opération d'obtention du jeton. Le code d'implémentation spécifique est le suivant :

-- 获取令牌
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

Parmi eux, KEYS[1] représente la clé de limitation actuelle, ARGV[1] représente la vitesse à laquelle les jetons sont introduits, ARGV[2] représente la capacité du seau et ARGV[3 ] représente l'heure actuelle.

2. Limitation de courant basée sur un algorithme d'entonnoir

L'algorithme d'entonnoir est également un algorithme de limitation de courant couramment utilisé. Son principe est un entonnoir, et les demandes s'écoulent dans l'entonnoir comme de l'eau. . Si l'entonnoir est plein, il déborde. Dans Redis, nous pouvons également utiliser des ensembles ordonnés (zset) et des scripts Lua pour implémenter l'algorithme d'entonnoir.

L'algorithme d'entonnoir doit maintenir un objet entonnoir pour enregistrer l'heure de la dernière requête et la capacité actuelle du bucket. Lorsqu'une nouvelle demande arrive, l'algorithme calculera l'augmentation de capacité de l'entonnoir en fonction de la différence entre l'heure actuelle et l'heure de la dernière demande. Si la capacité est inférieure à la capacité maximale du compartiment, la demande est autorisée à passer et la capacité est réduite sinon, la demande est rejetée ;

Le code d'implémentation spécifique est le suivant :

-- 获取令牌
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

Parmi eux, KEYS[1] représente la clé de limitation actuelle, ARGV[1] représente le taux d'ajout d'eau de l'entonnoir , et ARGV[2] représente la capacité de l'entonnoir, ARGV[3] représente l'heure actuelle.

Résumé

Le mécanisme de limitation de courant distribué fourni par Redis peut contrôler efficacement les accès simultanés et assurer la stabilité du système. Nous pouvons choisir l'algorithme de compartiment de jetons ou l'algorithme d'entonnoir comme algorithme de limitation actuel en fonction des besoins de l'entreprise, et l'implémenter via l'ensemble ordonné (zset) et le script Lua de Redis. Il convient de noter que lors de l'application du mécanisme de limitation actuel, les paramètres de l'algorithme doivent être raisonnablement configurés en fonction de scénarios commerciaux spécifiques et des caractéristiques du trafic afin d'éviter un impact négatif sur l'expérience utilisateur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn