How Distributed Locks Keep High‑Traffic Red‑Packet Systems Consistent
This article explains why traditional in‑process locks fail under massive concurrency, how distributed locks using Redis or Zookeeper ensure atomic updates across many servers, and details practical implementations, pitfalls like deadlocks, and strategies such as key expiration and ephemeral sequential nodes.
1. Why regular locks can’t scale
Traditional locks (e.g., synchronized or Lock) work only within a single JVM, so they cannot coordinate access across multiple servers. When a service receives tens of thousands of concurrent requests—such as a large‑scale red‑packet (红包) distribution during holidays—using a single server would cause overload or failure.
In a scenario with 100 servers handling 10 million users who must share a total of 100 million units of currency, each server would independently deduct from its own copy, potentially allocating up to 100 billion units, far exceeding the intended total.
2. How a distributed lock solves the problem
A distributed lock treats the whole cluster as a single application, providing a lock that lives outside any individual service. Before a server allocates a portion of the red‑packet, it must acquire the lock from a central manager (e.g., Redis). The manager atomically decrements the remaining total, guaranteeing that the sum of all allocations never exceeds the original amount.
Each request follows the same pattern: acquire lock → read remaining amount → deduct allocated amount → release lock. If the lock cannot be obtained, the request waits or retries.
3. Implementations of distributed locks
Redis‑based lock
Redis is single‑threaded for network I/O, so commands are executed atomically. The typical workflow uses SETNX key value to create a lock key; a return value of 1 means success, 0 means the lock is already held.
After the critical section, the lock is released with DEL key, which also returns 1 on success.
To avoid deadlocks when a client crashes before releasing the lock, an expiration time is set:
Set the key and immediately apply EXPIRE key timeout (seconds) so the lock auto‑releases.
Alternatively, store a timestamp as the value; other clients can check if the lock has expired and use GETSET key newValue to claim it.
Using GETSET ensures that only one client can successfully reset the lock after expiration, preventing multiple owners.
Zookeeper‑based lock
Zookeeper provides a hierarchical namespace of znodes. Nodes can be persistent, persistent‑sequential, ephemeral, or ephemeral‑sequential. Ephemeral nodes disappear when the client session ends, which naturally solves the dead‑lock problem caused by crashed clients.
Lock acquisition steps:
Create an ephemeral‑sequential znode under a lock directory (e.g., /lock/000000001).
All participants watch the node with the smallest sequence number.
When the smallest node is deleted (after its owner releases the lock), the next smallest node receives a notification and acquires the lock.
This approach also mitigates the “herd effect” because only the next waiter is notified, not all 99 remaining clients.
Both Redis and Zookeeper implementations must handle edge cases such as network partitions, clock skew, and ensuring that lock release is idempotent.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
