DEV Community

Rijul Rajesh
Rijul Rajesh

Posted on

How Redis Handles Concurrent Updates Without Traditional Locks

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 WATCHed 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"
Enter fullscreen mode Exit fullscreen mode

We read the balance (100). Now, in our application logic, we subtract 30, then:

> MULTI
> SET user:123:balance 70
> EXEC
Enter fullscreen mode Exit fullscreen mode

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 from EXEC) 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)