Este adevărat că scripturile Lua în Redis sunt atomice, iar comenzile individuale pot avea probleme de concurență?
Răspuns: DA, este complet adevărat!
Când execuți un script Lua în Redis:
-- Acest script este complet atomic
local current = redis.call('GET', 'counter')
current = tonumber(current) or 0
-- Simulăm o logică complexă
if current < 100 then
redis.call('SET', 'counter', current + 1)
redis.call('LPUSH', 'log', 'Incrementat la: ' .. (current + 1))
return current + 1
else
redis.call('SET', 'status', 'limit_reached')
return -1
endGaranție: Toate aceste operații se execută ca o singură unitate atomică.
// PROBLEMATIC - NU este atomic!
const current = await redis.get('counter');
const newValue = parseInt(current || 0) + 1;
// ⚠️ PERICOL: Între aceste două comenzi,
// alt client poate modifica 'counter'!
await redis.set('counter', newValue);counter = 5counter = 5 (în același timp)counter = 6counter = 6 (ar trebui să fie 7!)const luaScript = `
local current = redis.call('GET', KEYS[1])
current = tonumber(current) or 0
redis.call('SET', KEYS[1], current + 1)
return current + 1
`;
// Această operație este atomică
const result = await redis.eval(luaScript, 1, 'counter');┌─────────────┐ Script Lua ┌─────────────┐
│ Client │ ──────────────→ │ Server │
│ (Node.js, │ │ Redis │
│ Python, │ ←────────────── │ │
│ etc.) │ Rezultat │ │
└─────────────┘ └─────────────┘-- Toate acestea se execută atomic
redis.call('MULTI') -- Nu e nevoie de MULTI în Lua!
redis.call('SET', 'key1', 'value1')
redis.call('SET', 'key2', 'value2')
redis.call('INCR', 'counter')
-- Automat atomic// În loc de 3 round-trips separate:
await redis.get('key1');
await redis.set('key2', 'value');
await redis.incr('counter');
// Un singur round-trip cu Lua:
await redis.eval(script, 0);-- Logică care ar fi ineficientă pe client
local users = redis.call('SMEMBERS', 'active_users')
local result = {}
for i, user in ipairs(users) do
local score = redis.call('ZSCORE', 'leaderboard', user)
if score and tonumber(score) > 100 then
table.insert(result, user)
redis.call('SADD', 'premium_users', user)
end
end
return result-- Păstrează scripturile simple și focused
-- Evită logica prea complexă în LuaSCRIPT LOAD-- Bun: folosește parametri
local key = KEYS[1]
local increment = ARGV[1]
local current = redis.call('GET', key)
return redis.call('INCRBY', key, increment)-- Verifică că valorile există
local value = redis.call('GET', KEYS[1])
if not value then
return nil
end
-- continuă cu logica...-- Preferă scripturile scurte și focalizate
-- Evită logica de business complexă în LuaChatGPT avea perfect dreptate:
Scripturile Lua sunt instrumentul ideal pentru operațiile care necesită atomicitate și consistency în Redis, eliminând problemele de race conditions specifice comenzilor individuale.