Using Lua Scripting

1. Executing Scripts

CommandDescription
EVAL script numkeys key [key ...] arg [arg ...]Run inline script atomically

2. Caching Scripts

CommandDescription
SCRIPT LOAD scriptReturns SHA1; cache server-side
EVALSHA sha numkeys ...Execute cached script

3. Passing Keys and Arguments

Lua VarPurpose
KEYS[i]Key names (1-indexed); enables Cluster routing
ARGV[i]Arbitrary arguments

4. Using Redis Commands in Scripts

APIBehavior on Error
redis.call(cmd, ...)Aborts script with error
redis.pcall(cmd, ...)Returns error table; script continues

Example: Atomic compare-and-set

EVAL "if redis.call('GET', KEYS[1]) == ARGV[1] then \
  return redis.call('SET', KEYS[1], ARGV[2]) else return 0 end" \
  1 mykey "old" "new"

5. Returning Values from Scripts

Lua TypeRedis Return
numberInteger (truncated)
stringBulk string
table (array)Multi-bulk
false / nilNil
trueInteger 1
{err=...}Error reply

6. Understanding Script Atomicity

PropertyDetail
AtomicEntire script runs without interleaving
BlockingOther commands wait — keep scripts short

7. Checking Script Existence

CommandReturns
SCRIPT EXISTS sha [sha ...]Array of 0/1 per SHA

8. Flushing Script Cache

CommandOptions
SCRIPT FLUSH [ASYNC|SYNC]Clear all cached scripts

9. Killing Running Scripts

CommandLimitations
SCRIPT KILLOnly if script hasn't performed writes; otherwise SHUTDOWN NOSAVE

10. Debugging Scripts

ToolDescription
redis-cli --ldb -x eval ... 0Interactive Lua debugger
redis.log(level, msg)Log from inside script
SCRIPT DEBUG YES|SYNC|NOEnable debug mode

11. Handling Script Errors

FunctionUsage
redis.error_reply(msg)Return typed error
redis.status_reply(msg)Return status string

12. Implementing Atomic Operations

Example: Atomic rate-limit increment with TTL

EVAL "local c = redis.call('INCR', KEYS[1]) \
  if c == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end \
  return c" 1 rate:user:42 60
PatternUse
Multi-key CASRead-modify-write atomically
Conditional deleteVerify owner before DEL