WATCH for optimistic locking in Redis - Time & Space Complexity
When using WATCH in Redis, we want to see how the time to complete a transaction changes as we watch more keys.
We ask: How does watching keys affect the work Redis does before committing changes?
Analyze the time complexity of this Redis transaction using WATCH.
WATCH key1 key2 key3
MULTI
INCR key1
INCR key2
EXEC
This code watches three keys for changes, then starts a transaction to increment two keys, and finally tries to execute the transaction.
Look for repeated checks or loops inside the transaction process.
- Primary operation: Redis checks each watched key for changes before EXEC.
- How many times: Once per EXEC call, checking all watched keys.
As the number of watched keys grows, Redis must check more keys before running the transaction.
| Input Size (number of watched keys) | Approx. Operations |
|---|---|
| 3 | 3 key checks |
| 10 | 10 key checks |
| 100 | 100 key checks |
Pattern observation: The work grows directly with the number of watched keys.
Time Complexity: O(n)
This means the time to check keys grows linearly with how many keys you watch.
[X] Wrong: "Watching more keys does not affect performance because Redis is fast."
[OK] Correct: Even though Redis is fast, it still checks every watched key before executing, so more keys mean more work.
Understanding how WATCH scales helps you explain transaction costs clearly and shows you know how Redis handles concurrency.
What if we replaced WATCH with a Lua script for atomic updates? How would the time complexity change?
Practice
WATCH command in Redis optimistic locking?Solution
Step 1: Understand the role of WATCH in Redis
WATCH is used to monitor keys for any changes before a transaction starts.Step 2: Identify what happens if keys change
If any watched key changes before EXEC, the transaction is canceled to avoid conflicts.Final Answer:
To monitor keys for changes before executing a transaction -> Option AQuick Check:
WATCH detects key changes before transaction [OK]
- Thinking WATCH locks keys permanently
- Assuming WATCH deletes keys
- Believing WATCH creates backups
counter using optimistic locking?Solution
Step 1: Identify correct order for optimistic locking
You must first WATCH the key to monitor changes, then start MULTI for transaction.Step 2: Confirm command order
The correct order is WATCH counter, then MULTI, then commands like INCR, finally EXEC.Final Answer:
WATCH counter, MULTI, INCR counter, EXEC -> Option BQuick Check:
WATCH before MULTI for optimistic locking [OK]
- Starting MULTI before WATCH
- Running commands before MULTI
- Not using EXEC at the end
WATCH balance MULTI INCR balance EXEC
If another client modifies
balance after WATCH but before EXEC, what will be the result of EXEC?Solution
Step 1: Understand WATCH behavior on key change
If a watched key changes before EXEC, the transaction is aborted to prevent conflicts.Step 2: Identify EXEC result when aborting
When aborted, EXEC returns null (or nil) indicating the transaction did not run.Final Answer:
EXEC will fail and return null -> Option AQuick Check:
Key changed after WATCH causes EXEC to return null [OK]
- Assuming EXEC still increments key
- Expecting syntax error on EXEC
- Thinking EXEC retries automatically
WATCH stock MULTI DECR stock EXEC
But sometimes the stock count is not decremented even though no errors occur. What is the most likely cause?
Solution
Step 1: Analyze why stock is not decremented
If another client changes the watched key after WATCH, EXEC aborts the transaction silently.Step 2: Confirm command correctness
DECR syntax is correct and EXEC is present, so no syntax errors.Final Answer:
The stock key was modified by another client after WATCH -> Option CQuick Check:
Concurrent key change aborts transaction silently [OK]
- Blaming DECR syntax
- Forgetting EXEC command
- Thinking WATCH blocks commands
Solution
Step 1: Understand optimistic locking with conditional logic
You must WATCH the key, then GET its value before starting MULTI to ensure value is current.Step 2: Confirm correct command order
WATCH first, then GET value, then MULTI, then conditionally INCR, finally EXEC.Final Answer:
WATCH counter val = GET counter MULTI if val < 10: INCR counter EXEC -> Option DQuick Check:
GET before MULTI after WATCH ensures correct conditional update [OK]
- Starting MULTI before GET
- Getting value after MULTI
- Not watching key before GET
Ready to prove it?
Pass the test and this pattern moves unknown
