In the world of concurrent systems, data consistency is both a challenge and a priority. When multiple clients try to read and write to the same resource—say, a Redis key—without coordination, things can go wrong fast. This is where locking comes in. But not all locking is created equal.
What Is Optimistic Locking?
Optimistic locking is a concurrency control method that doesn’t lock the resource immediately. Instead, it watches it for changes and performs a check right before committing any updates. If someone else modified the resource in the meantime, your update gets rejected, and you can try again.
The core idea is:
“Let me do my work assuming no one else will interfere, but I’ll double-check before saving.”
Why Use Optimistic Locking in Redis?
Redis is a blazing-fast, in-memory data store—often used in highly concurrent environments. Traditional locking (like mutexes or semaphores) can add performance overhead or cause blocking, which goes against Redis’s low-latency nature.
Instead of locking a key, Redis gives you a way to observe it and act accordingly if someone else makes a change.
The Key Players: WATCH, MULTI, and EXEC
WATCH
This tells Redis:
“I care about this key. Let me know if it changes before I commit my transaction.”
You use it before starting a transaction. If the watched key is changed by another client before you call EXEC
, the whole transaction will be aborted.
MULTI
This starts the transaction block. You queue up commands just like any transaction system.
EXEC
This attempts to run all the commands you queued. But before doing so, Redis checks if any of the WATCH
ed keys changed. If they did, EXEC
returns nil
, and nothing is executed.
Example: Updating a Balance Safely
Let’s say we’re building a wallet service and want to deduct an amount from a user’s balance.
> WATCH user:123:balance
> GET user:123:balance
"100"
We read the balance (100). Now, in our application logic, we subtract 30, then:
> MULTI
> SET user:123:balance 70
> EXEC
If no other client modified user:123:balance
after the WATCH
, the EXEC
will go through.
But if someone else updated the balance in between, EXEC
will return nil
, signaling that our transaction was aborted. We can then retry the whole process.
Key Advantages
- Non-blocking: No one gets locked out. Clients can keep reading and writing.
- Fast-fail: If a key changes, Redis doesn’t do extra work—your transaction is just skipped.
-
Simple retry logic: Failures are easy to detect (
nil
fromEXEC
) and retry if needed.
When Not to Use Optimistic Locking
While optimistic locking is elegant and fast, it’s not always the best tool:
- In systems with high contention (multiple processes or threads are competing for the same resource), the number of retries may hurt performance.
- If you need strong guarantees that only one client can act at a time, a more traditional locking mechanism (like
SETNX
-based locks) might be better.
Wrapping up
Optimistic locking in Redis is a lightweight, elegant way to ensure data integrity without sacrificing speed. It’s built for real-world systems where conflicts are rare, but safety is still critical.
If you're a software developer who enjoys exploring different technologies and techniques like this one, check out LiveAPI. It’s a super-convenient tool that lets you generate interactive API docs instantly.
LiveAPI helps you discover, understand and use APIs in large tech infrastructures with ease!
So, if you’re working with a codebase that lacks documentation, just use LiveAPI to generate it and save time!
You can instantly try it out here! 🚀
Top comments (0)