Atomicity and the single thread
Redis executes one command at a time. That one fact makes INCR safe, makes KEYS * dangerous, and explains MULTI and Lua.
One queue, one executor
- Three clients send commands at the same instant: A and B both INCR views, C reads it.
- They land in one queue in arrival order. Network reads and writes can use I/O threads (Redis 6+), but commands still run on one thread.
- The thread runs A's INCR to the end: read 10, add 1, write 11. Nothing else can run in between.
- Then B's INCR: 11 → 12. Then C's GET sees 12. No locks were needed anywhere.
- The flip side: one slow command — KEYS *, HGETALL on a million-field hash, a long Lua script — makes every client behind it wait.
Race: GET+SET vs INCR
Lab · two app servers each add 100 likes at the same time
expected200
actual—
Run both. The trace shows the first operations in the order Redis received them.
Group commands: MULTI / EXEC
- MULTI opens a transaction. Redis replies OK and starts queueing.
- DECRBY and RPUSH reply QUEUED. Nothing has run yet, so you cannot read their results inside the transaction.
- EXEC runs the whole queue in one go. No other client's command can slip in between.
- There is no rollback. If one command fails at run time (wrong type), the others still apply. Validate first.
- Need to read, decide, then write (“only if stock > 0”)? Use a Lua script — it runs as one atomic command — or WATCH + MULTI and retry.
Pipeline, MULTI, WATCH, Lua
| Pipeline | Send 100 commands without waiting for each reply. Faster, not atomic — others can interleave. |
|---|---|
| MULTI / EXEC | Queue, then run as a block. Atomic, no logic — you cannot branch on a value. |
| WATCH + MULTI | Read, decide in the app, EXEC fails if a watched key changed. Optimistic — retry on failure. |
| Lua (EVAL / FUNCTION) | Logic runs inside Redis. Atomic with logic — keep scripts short; they block like any command. |
Try a transaction
Quick check
Your app does
GET balance, adds 50, then SET balance. Two requests do it at once. What can happen?
Show answer
A lost update: both read the same old value. Use INCRBY balance 50, or a Lua script if there is a rule like “never below 0”.
Is a pipeline of SET a and SET b atomic?
Show answer
No. It only saves round trips. Another client can run between them. Wrap them in MULTI/EXEC if they must land together.