Una dintre cele mai răspândite utilizări ale Redis în companiile mari este Rate Limiting (limitarea ratei de cereri HTTP per adresă IP, token de utilizator sau cheie API). Pentru a preveni condițiile de concurență (race conditions) în mediile distribuite cu zeci de mii de cereri concurente, algoritmul optim se implementează printr-un script Lua executat atomic direct în interiorul serverului Redis via comanda EVAL.
Algoritmul Fixed Window Rate Limiter atomic prin Script Lua
-- Script Lua pentru verificare și incrementare atomică
-- KEYS[1] = cheia de identificare a ratei (ex: 'ratelimit:192.168.1.50')
-- ARGV[1] = limita maximă admisă (ex: 100 cereri)
-- ARGV[2] = fereastra de timp în secunde (ex: 60 secunde)
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call('get', key)
if current and tonumber(current) >= limit then
-- Limita a fost atinsă, respinge cererea (HTTP 429 Too Many Requests)
return 0
else
-- Incrementează contorul
current = redis.call('incr', key)
if tonumber(current) == 1 then
-- Dacă este prima cerere din fereastră, activează expirarea automată
redis.call('expire', key, window)
end
-- Autorizează cererea
return 1
end
Apelarea scriptului din linia de comandă redis-cli
# Execuție EVAL: 1 cheie ('ratelimit:ip:10.0.0.1'), limită 5 cereri, fereastră 60s
EVAL "local c = redis.call('get', KEYS[1]) if c and tonumber(c) >= tonumber(ARGV[1]) then return 0 else c = redis.call('incr', KEYS[1]) if tonumber(c) == 1 then redis.call('expire', KEYS[1], ARGV[2]) end return 1 end" 1 "ratelimit:ip:10.0.0.1" 5 60
# Returnează 1 -> Cererea este permisă (răspunde cu datele solicitate)
# Returnează 0 -> Limita a fost depășită (răspunde cu HTTP 429)
De ce să folosești Scripturi Lua în Redis
- Atomicitate absolută garantată: Scriptul Lua se execută fără a fi întrerupt de nicio altă comandă, eliminând riscul ca doi utilizatori să depășească limita în aceeași milisecundă.
- Zero latență de rețea intermediară: Logica condițională (
if / else) rulează direct pe serverul Redis, fără a trimite valori înainte și înapoi către aplicația backend. - Optimizare prin SHA1: Scripturile pot fi pre-încărcate prin
SCRIPT LOADși apelate ultra-rapid prin codul hash cuEVALSHA.