Distributed Locking Mechanisms
In this lesson, you will learn how to synchronize access to shared resources across multiple independent application workers using a central coordination point.
When your application scales horizontally, you often have multiple instances of a service running simultaneously. If these workers need to perform an operation on a shared resource—such as updating a financial balance or processing a specific task—they might overlap, leading to race conditions where data becomes inconsistent. Since local memory locks only affect a single process, you need a distributed lock that exists outside of your application workers.
The Mechanism: Mutual Exclusion via Redis
We can use an in-memory key-value store, like Redis, to act as a "distributed mutex." The logic is simple: before a worker performs a critical task, it must successfully set a specific key in the database.
Consider the following approach using the SET command with arguments:
# Attempt to acquire the lock
# NX: Only set if the key does not exist
# EX: Set an expiry time (e.g., 10 seconds) to prevent permanent deadlocks
SET resource_lock "worker_id_1" NX EX 10
- Acquire: The worker attempts to
SETa unique key. If the command returnsOK, the worker has exclusive access. If it returnsnil(or fails), the key is already held by another worker, and the current worker must wait or retry. - Execute: The worker performs its critical section (the shared resource update).
- Release: Once finished, the worker deletes the key, allowing other workers to acquire it.
Why Timeouts Matter
A critical detail in distributed locking is the expiration (EX). If a worker crashes while holding a lock, that lock could theoretically stay in the system forever, blocking all other workers. By attaching an expiry time, you guarantee that the lock will eventually be released even if the process holding it terminates unexpectedly.
While this simple implementation is powerful, in high-stakes systems, you must also ensure that a worker only deletes the lock it created, often by verifying the worker_id stored in the value before executing the delete command.
Key Takeaway: Distributed locking uses an external, atomic key-value operation with a TTL (Time-To-Live) to enforce mutual exclusion across independent processes, preventing race conditions on shared data.