📖 Scenario: You are managing a Redis database for a simple online store. You want to safely update the stock count of a product without interference from other operations.
🎯 Goal: Build a Lua script that atomically checks the stock of a product and decreases it by a specified amount only if enough stock is available.
📋 What You'll Learn
Create a Redis key with the initial stock count for a product.
Define a variable for the amount to decrease the stock.
Write a Lua script that atomically checks if the stock is sufficient and decreases it.
Add the final command to execute the Lua script using Redis EVAL.
💡 Why This Matters
🌍 Real World
Managing stock counts in an online store requires atomic updates to prevent overselling.
💼 Career
Understanding Lua scripting in Redis is valuable for backend developers working with caching and real-time data stores.
Progress0 / 4 steps
1
DATA SETUP: Create a Redis key for product stock
Create a Redis key called product_stock and set its value to 100 to represent the initial stock count.
Redis
Hint
Use the Redis SET command to create the key and assign the value.
2
CONFIGURATION: Define the amount to decrease stock
Define a Lua variable called decrease_amount and set it to 5 to represent how many items to remove from stock.
Redis
Hint
Use local decrease_amount = 5 to define the variable inside the Lua script.
3
CORE LOGIC: Write Lua script for atomic stock decrease
Write a Lua script that uses redis.call('GET', 'product_stock') to get the current stock, converts it to a number, checks if it is greater or equal to decrease_amount, and if yes, decreases the stock by decrease_amount using redis.call('SET', 'product_stock', new_stock). Use variables current_stock and new_stock.
Redis
Hint
Use tonumber to convert the stock string to a number. Use if to check stock and redis.call('SET', ...) to update.
4
COMPLETION: Execute the Lua script atomically with Redis EVAL
Write the Redis EVAL command to run the Lua script atomically. Use the full Lua script as a string, pass 0 for the number of keys, and no additional arguments.
Redis
Hint
Use EVAL with the Lua script as a string and 0 keys to run the script atomically.
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
Step 1: Understand atomicity in Redis
Atomicity means commands run fully or not at all, preventing partial updates.
Step 2: Role of Lua scripts with EVAL
Lua scripts run all commands inside them as a single atomic operation in Redis.
Final Answer:
It ensures multiple commands run atomically without interference. -> Option A
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
Step 1: Understand tonumber behavior
tonumber(nil) returns nil, so nil + 1 causes error.
Step 2: Check script for nil handling
Script does not check if count is nil before adding 1, causing runtime error if key missing.
Final Answer:
Missing check if count is nil before tonumber conversion. -> Option A
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
Step 1: Handle missing key safely
Using 'or "0"' ensures tonumber gets '0' if key missing, avoiding nil errors.
Step 2: Check condition and increment
Condition 'v < 100' matches requirement to increment only if less than 100.
Step 3: Return updated or current value
Returns v+1 if incremented, else returns current v.
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
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 unknownstrongwhile earning +1 Grip toward your certificate.