Using Lua Scripting
1. Executing Scripts
| Command | Description |
|---|---|
EVAL script numkeys key [key ...] arg [arg ...] | Run inline script atomically |
2. Caching Scripts
| Command | Description |
|---|---|
SCRIPT LOAD script | Returns SHA1; cache server-side |
EVALSHA sha numkeys ... | Execute cached script |
3. Passing Keys and Arguments
| Lua Var | Purpose |
|---|---|
KEYS[i] | Key names (1-indexed); enables Cluster routing |
ARGV[i] | Arbitrary arguments |
4. Using Redis Commands in Scripts
| API | Behavior 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 Type | Redis Return |
|---|---|
| number | Integer (truncated) |
| string | Bulk string |
| table (array) | Multi-bulk |
| false / nil | Nil |
| true | Integer 1 |
{err=...} | Error reply |
6. Understanding Script Atomicity
| Property | Detail |
|---|---|
| Atomic | Entire script runs without interleaving |
| Blocking | Other commands wait — keep scripts short |
7. Checking Script Existence
| Command | Returns |
|---|---|
SCRIPT EXISTS sha [sha ...] | Array of 0/1 per SHA |
8. Flushing Script Cache
| Command | Options |
|---|---|
SCRIPT FLUSH [ASYNC|SYNC] | Clear all cached scripts |
9. Killing Running Scripts
| Command | Limitations |
|---|---|
SCRIPT KILL | Only if script hasn't performed writes; otherwise SHUTDOWN NOSAVE |
10. Debugging Scripts
| Tool | Description |
|---|---|
redis-cli --ldb -x eval ... 0 | Interactive Lua debugger |
redis.log(level, msg) | Log from inside script |
SCRIPT DEBUG YES|SYNC|NO | Enable debug mode |
11. Handling Script Errors
| Function | Usage |
|---|---|
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
| Pattern | Use |
|---|---|
| Multi-key CAS | Read-modify-write atomically |
| Conditional delete | Verify owner before DEL |