Nivel 2 · 25 min
Lua Scripting en Redis
Redis permite ejecutar scripts Lua de forma atómica — el script completo se ejecuta sin interrupciones, como una transacción. Esto resuelve problemas de race conditions que no se pueden solucionar con comandos individuales ni con MULTI/EXEC cuando necesitás leer y decidir antes de escribir.
Atomicidad de Lua en Redis
Cuando ejecutás EVAL script, Redis ejecuta el script en un solo thread, sin que otros comandos puedan intercalarse. Esto garantiza atomicidad completa: podés leer un valor, hacer una decisión basada en él y escribir el resultado — todo sin race conditions. EVAL es diferente de MULTI/EXEC: con MULTI/EXEC no podés leer en el medio de la transacción para tomar decisiones condicionales.
Rate limiting con Lua
Un caso de uso canónico es el rate limiter: verificar si el usuario pasó el límite de requests y, si no lo hizo, incrementar el contador en una sola operación atómica. Sin Lua, este patrón tiene un race condition entre el GET y el INCR. El script Lua lee el valor actual, decide, incrementa y establece TTL — todo atómicamente. Implementación: ventana fija, ventana deslizante con Sorted Set.
EVALSHA y cache de scripts
EVAL envía el script completo cada vez — ineficiente para scripts frecuentes. SCRIPT LOAD carga el script en Redis y devuelve un SHA1. Luego usás EVALSHA sha1 para ejecutar por hash. Redis cachea el script en todos los nodos. Si el script no está cacheado (nodo reiniciado), Redis devuelve NOSCRIPT — tu cliente debe volver a EVAL y cargar. Esto es importante en Cluster mode donde distintos nodos pueden tener distintos caches.
Code example
-- Rate limiter: atomico, sin race condition
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call(''INCR'', key)
if current == 1 then
redis.call(''EXPIRE'', key, window)
end
if current '>' limit then
return 0 -- rechazado
else
return 1 -- permitido
end