CHAPTER 10
Intermediate
Redis Transactions | MULTI, EXEC, and WATCH Commands
Updated: May 16, 2026
15 min read
# CHAPTER 10
Transactions and Atomic Operations
1. Introduction
Imagine you are building a banking application. Alice transfers $50 to Bob. The backend code must do two things: 1) Subtract $50 from Alice's account, and 2) Add $50 to Bob's account. But what if the server crashes exactly between step 1 and step 2? Alice lost her money, and Bob never received it. The money evaporated. To prevent this catastrophic financial error, database operations must be Atomic (meaning "Indivisible"). Either both steps happen perfectly, or neither step happens. In this chapter, we will learn how to execute atomic Transactions in Redis.2. Learning Objectives
By the end of this chapter, you will be able to:- Define the concept of a Database Transaction.
-
Initialize a transaction block using
MULTI.
-
Execute a queued transaction using
EXEC.
-
Cancel a transaction using
DISCARD.
-
Implement Optimistic Locking using the
WATCHcommand.
3. The Basics of MULTI and EXEC
In Redis, a transaction is simply a way to group multiple commands together so they execute sequentially without any other user's commands interrupting them.-
1.
Open your
redis-cli.
- 2. Start the transaction block:
bash
bash
DISCARD
``
*(Redis responds OK. The queue is instantly flushed, no data is changed, and you exit Transaction Mode).*
5. The Threat of Race Conditions
While MULTI/EXEC ensures commands run together, it does *not* prevent other users from changing the data *before* you type EXEC.
Imagine you are writing a script to buy the last concert ticket:
-
1.
Script checks
GET tickets_left (Result: 1).
-
2.
Script prepares
MULTI.
-
3.
*At this exact millisecond, another user buys the ticket!*
-
4.
Script queues
DECR tickets_left.
-
5.
Script runs
EXEC.
*(Result: tickets_left drops to -1. You accidentally sold a ticket that doesn't exist).*
6. Optimistic Locking (The WATCH Command)
To solve the Race Condition above, Redis provides the WATCH command. It acts like a security camera on a specific key.
-
1.
Tell Redis to watch the key:
`bash
WATCH tickets_left
`
-
2.
Your script sees there is 1 ticket left. It starts a transaction:
`bash
MULTI
DECR tickets_left
`
-
3.
If any other user changes
tickets_left right now, the WATCH camera detects it.
-
4.
You run
EXEC.
-
5.
Because the camera detected tampering, Redis will instantly ABORT your
EXEC command and return (nil)! It refuses to execute the transaction, saving you from negative inventory!
7. Why Redis Transactions are Different
If you are coming from MySQL, you must understand a critical difference.
In MySQL, if the 2nd step of a transaction fails (e.g., a syntax error), MySQL automatically "Rolls Back" (undoes) the 1st step.
Redis DOES NOT SUPPORT ROLLBACKS.
If you queue 3 commands, and the 2nd command tries to run INCR on a text string (which throws an error), Redis will still successfully execute the 1st and 3rd commands! Redis assumes errors are the fault of the programmer, and it refuses to slow down the engine to support complex rollback logic.
8. Mini Project: The Secure Transfer
Let's safely transfer points in a video game using Optimistic Locking.
-
1.
WATCH player1:score player2:score (Lock both accounts).
-
2.
Read the scores in your backend code. Verify Player 1 has enough points.
-
3.
MULTI
-
4.
DECRBY player1:score 100
-
5.
INCRBY player2:score 100
-
6.
EXEC
*(If Player 1 tried to double-spend their points in a separate browser tab while this was happening, the WATCH command will detect the state change and instantly block this EXEC from processing!).*
9. Common Mistakes
-
Using WATCH inside MULTI: You cannot start watching a key after you have already started the transaction. The
WATCH command must always be executed *before* typing MULTI.
10. Best Practices
-
Use Lua Scripts Instead: While
MULTI/EXEC is good, modern Redis architecture heavily favors using Lua Scripts. You can write a small script containing IF/ELSE logic and send the entire script to Redis. Redis executes Lua scripts completely atomically by default, entirely removing the need for complex WATCH logic!
11. Exercises
-
1.
What command initiates a transaction queue?
-
2.
What command physically executes the queued transaction?
12. Redis Challenges
You execute MULTI. You queue SET key1 "A". You queue INCR key1 (which is impossible, because you cannot increment the letter A). You queue SET key2 "B". You run EXEC. Describe the exact final state of the database.
*(Answer: key1 will be set to "A". The INCR command will throw an error and fail. However, because Redis does not support Rollbacks, the transaction will continue, and key2 will successfully be set to "B").*
13. MCQ Quiz with Answers
Question 1
When architecting an inventory checkout system in Redis, what is the explicit mechanical purpose of the WATCH command?
Question 2
How does the architectural behavior of a Redis transaction fundamentally differ from a strict Relational Database (SQL) transaction when an error occurs during EXEC?
14. Interview Questions
-
Q: Define "Optimistic Locking" in the context of high-concurrency systems. Walk through a specific code flow utilizing
WATCH, MULTI, and EXEC to prevent a double-spend scenario in a digital wallet application.
-
Q: Explain why the creator of Redis explicitly chose not to implement transactional Rollbacks (like those found in PostgreSQL). How does this design choice align with the core philosophy of In-Memory databases?
15. FAQs
Q: Does WATCH lock the key so nobody else can read it?
A: No! WATCH is an *Optimistic* lock. It does not stop other people from reading or writing to the key. It simply says, "I am going to watch this key. If anyone else changes it, just cancel my next transaction." It is completely non-blocking, making it incredibly fast.
16. Summary
You are now capable of executing complex, multi-step workflows with absolute mathematical safety. By mastering MULTI, EXEC, and the Optimistic Locking power of WATCH`, you can ensure that high-concurrency financial operations execute flawlessly without data corruption.