Blocul tradițional de tranzacții Redis (MULTI / EXEC) este un simplu container secvențial: comenzile sunt puse într-o coadă și executate atomic, dar nu permit fluxuri condiționate de tip IF/ELSE bazate pe rezultatul unei comenzi anterioare din aceeași tranzacție.
Pentru a rula logică de afaceri complexă direct pe server, fără round-trip-uri lente de rețea și cu garanție de atomicitate absolută (nicio altă comandă a unui alt client nu poate interveni la mijloc), Redis include un motor încorporat de Lua.
Trecerea de la Scripting Lua la Redis Functions (Redis 7+)
-- Codul unei biblioteci Lua moderne pentru Redis Functions:
#!lua name=gestiune_stoc
redis.register_function('scade_stoc', function(keys, args)
local cheie_produs = keys[1]
local cantitate_ceruta = tonumber(args[1])
local stoc_curent = tonumber(redis.call('GET', cheie_produs) or '0')
if stoc_curent >= cantitate_ceruta then
redis.call('DECRBY', cheie_produs, cantitate_ceruta)
return { 1, stoc_curent - cantitate_ceruta } -- Succes, stoc rămas
else
return { 0, stoc_curent } -- Eșec: stoc insuficient
end
end)
Încărcarea și Apelarea unei Funcții Redis
# 1. Încărcăm funcția pe server (stocată permanent în metadate și replicată la replici):
FUNCTION LOAD "#!lua name=gestiune_stoc \n redis.register_function('scade_stoc', function(keys, args) local k = keys[1]; local q = tonumber(args[1]); local s = tonumber(redis.call('GET', k) or '0'); if s >= q then redis.call('DECRBY', k, q); return {1, s - q}; else return {0, s}; end end)"
# 2. Inițializăm un stoc de test:
SET produs:laptop 10
# 3. Apelăm funcția prin FCALL:
# Sintaxă: FCALL ...
FCALL scade_stoc 1 produs:laptop 3
# Răspuns:
# 1) (integer) 1 (operațiune reușită)
# 2) (integer) 7 (stoc rămas)
FCALL scade_stoc 1 produs:laptop 15
# Răspuns:
# 1) (integer) 0 (eșec: stoc insuficient)
# 2) (integer) 7 (stocul a rămas neatins)
De Ce Redis Functions Sunt Superioare Scripturilor EVAL/EVALSHA?
- Persistență Nativă: Funcțiile sunt incluse direct în fișierele de snapshot RDB și jurnalele AOF, fiind restaurate automat la repornire.
- Management ca la Baze de Date: Codul este partajat de toți clienții fără a forța fiecare aplicație să trimită hash-ul SHA al scriptului la pornire.
- Modularitate și Versiuni: Funcțiile sunt grupate în biblioteci numite (libraries), facilitând deployment-ul în CI/CD.