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!