Bird
Raised Fist0
Redisquery~20 mins

Atomic operations with Lua in Redis - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Lua Atomic Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ query_result
intermediate
2:00remaining
What is the output of this Lua script in Redis?
Consider the following Lua script executed in Redis:
redis.call('SET', 'counter', 10)
local val = redis.call('INCRBY', 'counter', 5)
return val

What will be the output after running this script?
Redis
redis.call('SET', 'counter', 10)
local val = redis.call('INCRBY', 'counter', 5)
return val
Anil
B10
C5
D15
Attempts:
2 left
💡 Hint
Remember that INCRBY increases the value stored at the key by the given amount and returns the new value.
📝 Syntax
intermediate
2:00remaining
Which Lua script will cause a syntax error in Redis?
Identify the Lua script that will cause a syntax error when executed in Redis.
Alocal val = redis.call('INCR', 'counter') return val
Blocal val = redis.call('GET', 'key' return val
Clocal val = redis.call('SET', 'key', 'value') return val
Dreturn redis.call('GET', 'key')
Attempts:
2 left
💡 Hint
Look for missing or misplaced parentheses.
❓ optimization
advanced
2:00remaining
Which Lua script is the most efficient for incrementing a counter and returning its new value?
You want to increment a Redis key 'visits' atomically and get the updated value. Which script is the most efficient?
Areturn redis.call('INCR', 'visits')
B
local current = redis.call('GET', 'visits')
local new = tonumber(current) + 1
redis.call('SET', 'visits', new)
return new
C
redis.call('SET', 'visits', redis.call('GET', 'visits') + 1)
return redis.call('GET', 'visits')
D
local new = redis.call('INCRBY', 'visits', 1)
return new
Attempts:
2 left
💡 Hint
Consider atomicity and number of Redis calls.
🧠 Conceptual
advanced
2:00remaining
Why are Lua scripts in Redis considered atomic?
Choose the best explanation for why Lua scripts executed in Redis are atomic.
ABecause Redis queues Lua scripts and executes them one at a time without interruption.
BBecause Redis locks the entire database during script execution, preventing other commands.
CBecause Lua scripts run in a separate thread from Redis commands.
DBecause Lua scripts automatically rollback if an error occurs.
Attempts:
2 left
💡 Hint
Think about how Redis handles commands and scripts internally.
🔧 Debug
expert
2:00remaining
What error does this Lua script raise in Redis?
Given the Lua script:
local val = redis.call('INCRBY', 'counter', 'five')
return val

What error will Redis return when executing this script?
Redis
local val = redis.call('INCRBY', 'counter', 'five')
return val
Anil
BSyntaxError: unexpected string
CERR value is not an integer or out of range
DTypeError: argument must be a number
Attempts:
2 left
💡 Hint
INCRBY expects a numeric increment value.

Practice

(1/5)
1. What is the main benefit of using Lua scripts with Redis EVAL command?
easy
A. It ensures multiple commands run atomically without interference.
B. It speeds up Redis server startup time.
C. It allows Redis to store Lua scripts permanently.
D. It automatically backs up Redis data to disk.

Solution

  1. Step 1: Understand atomicity in Redis

    Atomicity means commands run fully or not at all, preventing partial updates.
  2. Step 2: Role of Lua scripts with EVAL

    Lua scripts run all commands inside them as a single atomic operation in Redis.
  3. Final Answer:

    It ensures multiple commands run atomically without interference. -> Option A
  4. Quick Check:

    Atomic operations = safe multi-command execution [OK]
Hint: Lua scripts run all commands atomically in Redis [OK]
Common Mistakes:
  • Thinking Lua scripts speed up server startup
  • Confusing script storage with atomicity
  • Assuming Lua scripts backup data automatically
2. Which of the following is the correct syntax to run a Lua script that increments a Redis key counter by 1 using EVAL?
easy
A. EVAL "return redis.call('INCR', 'counter')" 0
B. EVAL "return redis.call('INCR', ARGV[1])" 1 counter
C. EVAL "return redis.call('INCR', KEYS[1])" 0 counter
D. EVAL "return redis.call('INCR', KEYS[1])" 1 counter

Solution

  1. Step 1: Understand EVAL syntax

    EVAL script numkeys key1 key2 ... args ...; KEYS[] holds keys, ARGV[] holds arguments.
  2. Step 2: Identify correct usage for increment

    Since 'counter' is a key, it should be passed as KEYS[1] with numkeys=1.
  3. Final Answer:

    EVAL "return redis.call('INCR', KEYS[1])" 1 counter -> Option D
  4. Quick Check:

    Use KEYS for keys, ARGV for arguments [OK]
Hint: Keys go in KEYS[], count keys correctly [OK]
Common Mistakes:
  • Passing keys in ARGV instead of KEYS
  • Setting numkeys to 0 when keys are used
  • Using string literal instead of KEYS[1]
3. Given the Lua script run with EVAL below, what will be the output if the key visits does not exist initially?
EVAL "local v = redis.call('GET', KEYS[1]) if not v then v = 0 end v = v + 1 redis.call('SET', KEYS[1], v) return v" 1 visits
medium
A. nil
B. 1
C. 0
D. Error: attempt to perform arithmetic on a nil value

Solution

  1. Step 1: Analyze GET result when key missing

    redis.call('GET', KEYS[1]) returns nil if key doesn't exist.
  2. Step 2: Check the if condition

    if not v then v = 0 end executes since v is nil, setting v to 0.
  3. Step 3: Perform arithmetic and SET

    v = 0 + 1 = 1; redis.call('SET', KEYS[1], 1); return 1.
  4. Final Answer:

    1 -> Option B
  5. Quick Check:

    Nil handled by if not v, outputs 1 [OK]
Hint: Script checks nil before math, outputs 1 [OK]
Common Mistakes:
  • Overlooking the 'if not v then v = 0 end' check
  • Assuming nil causes arithmetic error despite handling
  • Thinking GET nil leads to error without reading full script
4. Identify the error in this Lua script used with Redis EVAL:
EVAL "local count = redis.call('GET', KEYS[1]) count = tonumber(count) + 1 redis.call('SET', KEYS[1], count) return count" 1 visits
medium
A. Missing check if count is nil before tonumber conversion.
B. Incorrect number of keys specified in EVAL command.
C. Using redis.call instead of redis.pcall causes failure.
D. The return statement should be outside the script string.

Solution

  1. Step 1: Understand tonumber behavior

    tonumber(nil) returns nil, so nil + 1 causes error.
  2. Step 2: Check script for nil handling

    Script does not check if count is nil before adding 1, causing runtime error if key missing.
  3. Final Answer:

    Missing check if count is nil before tonumber conversion. -> Option A
  4. Quick Check:

    Always check nil before tonumber and math [OK]
Hint: Check nil before tonumber and math operations [OK]
Common Mistakes:
  • Assuming tonumber(nil) returns 0
  • Ignoring nil checks before arithmetic
  • Confusing redis.call and redis.pcall usage
5. You want to atomically increment a Redis key page_views only if its current value is less than 100. Which Lua script snippet correctly implements this logic using EVAL?
hard
A. local v = redis.call('GET', KEYS[1]) if v < 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end
B. local v = tonumber(redis.call('GET', KEYS[1])) if v <= 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end
C. local v = tonumber(redis.call('GET', KEYS[1]) or '0') if v < 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end
D. local v = tonumber(redis.call('GET', KEYS[1]) or '0') if v <= 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end

Solution

  1. Step 1: Handle missing key safely

    Using 'or "0"' ensures tonumber gets '0' if key missing, avoiding nil errors.
  2. Step 2: Check condition and increment

    Condition 'v < 100' matches requirement to increment only if less than 100.
  3. Step 3: Return updated or current value

    Returns v+1 if incremented, else returns current v.
  4. Final Answer:

    local v = tonumber(redis.call('GET', KEYS[1]) or '0') if v < 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end -> Option C
  5. Quick Check:

    Safe nil handling + correct condition = local v = tonumber(redis.call('GET', KEYS[1]) or '0') if v < 100 then redis.call('INCR', KEYS[1]) return v + 1 else return v end [OK]
Hint: Use 'or "0"' to avoid nil, check '< 100' strictly [OK]
Common Mistakes:
  • Not handling nil key values
  • Using <= 100 instead of < 100
  • Forgetting to convert GET result to number
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard