Implementación de scripts Lua en Redis
Ventajas fundamentales
- Ejecución atómica: Los scripts Lua se ejecutan de manera indivisible dentro de Redis, eliminando la necesidad de meacnismos transaccionales adicionales.
- Rendimiento optimizado: Los scripts se almacenan en caché en el servidor tras su carga inicial. Lua, implementado en C, ofrece velocidad de ejecución superior y soporte multiplataforma.
- Eficiencia de red: Múltiples operaciones pueden combinarse en un solo script, minimizando las comunicaciones de red y el consumo de conexiones.
Comandos esenciales
eval <script_lua> <num_keys> [key ...] [arg ...]
// Ejecuta un script Lua directamente.
script load <script_lua>
// Almacena el script en caché y devuelve su digestión SHA1.
evalsha <sha1> <num_keys> [key ...] [arg ...]
// Ejecuta un script previamente almacenado usando su SHA1.
script exists <sha1>
// Verifica la existencia de un script cacheado (0: no, 1: sí).
script flush
// Elimina todos los scripts almacenados en el servidor.
script kill
// Detiene la ejecución de un script Lua en curso (solo operaciones de lectura).
redis-cli --eval <ruta_script> [key ...] , [arg ...]
// Ejecuta un script Lua desde un archivo externo.
Ejemplos prácticos
Uso directo con EVAL
eval "local ttl = tonumber(ARGV[2])
redis.call('SETEX', KEYS[1], ttl, ARGV[1])
return true" 1 usuario_sesion token_abc123 1800
Caché de scripts con SCRIPT LOAD
script load "local valor = redis.call('GET', KEYS[1])
if not valor then
redis.call('SET', KEYS[1], ARGV[1])
return ARGV[1]
end
return valor"
Ejecución mediante SHA1 con EVALSHA
evalsha "b53db15d1c74e222872348f91281a029f6c301e3" 1 clave_configuracion valor_predeterminado
Verificación de existencia
script exists "b53db15d1c74e222872348f91281a029f6c301e3"
Limpieza de caché
script flush
Terminación de scripts
# Script con operación de lectura consumidora de tiempo
redis> eval "local i = 0
while i < 1000000 do
redis.call('GET', KEYS[1])
i = i + 1
end" 1 datos_temporales
# Detener script de lectura
redis> script kill
Ejecución desde archivo
Para un bloqueo distribuido simple, el siguiente script podría almcaenarse como lock_manager.lua:
-- Implementación de bloqueo distribuido
local lock_key = KEYS[1]
local lock_value = ARGV[1]
local expire_time = tonumber(ARGV[2])
if redis.call('SETNX', lock_key, lock_value) == 1 then
redis.call('EXPIRE', lock_key, expire_time)
return 1
else
local current_value = redis.call('GET', lock_key)
if current_value == lock_value then
redis.call('EXPIRE', lock_key, expire_time)
return 1
end
return 0
end
Se ejecutaría mediante:
redis-cli --eval lock_manager.lua lock:recurso_unico , "session_456" 300