Pessimistic, Optimistic & Distributed Locks: Core Concepts, Scenarios & Tips
This article explains the fundamental ideas behind pessimistic, optimistic, and distributed locking, compares their strengths and weaknesses, outlines typical application scenarios such as inventory deduction, banking transfers, and cache protection, and provides concrete implementation examples using SQL row locks, version fields, CAS, Redis WATCH, and Lua scripts.
Introduction
Lock mechanisms guarantee data consistency and prevent resource contention in concurrent and distributed systems. The three primary models—pessimistic locking, optimistic locking, and distributed locking—embody different assumptions about conflict probability and are suited to distinct scenarios.
Core Concepts
Pessimistic Lock
Assumption : Conflicts are likely.
Strategy : Acquire an exclusive lock before accessing the resource.
Optimistic Lock
Assumption : Conflicts are rare.
Strategy : Perform operations without a lock, then verify that no conflicting update occurred before committing.
Distributed Lock
Purpose : Provide mutual exclusion across multiple processes or nodes.
Implementation : Can be built using either pessimistic or optimistic techniques, typically with a central coordination service such as Redis.
Pessimistic Lock
Typical Use Cases
Flash‑sale inventory deduction – prevents overselling.
Bank transfers – serializes balance updates.
Order status updates – avoids duplicate payments.
Concurrent file writes – prevents corruption.
Database Implementation Example (SQL)
BEGIN;
SELECT quantity FROM products WHERE id = 1 FOR UPDATE;
-- check stock, compute new_quantity
UPDATE products SET quantity = new_quantity WHERE id = 1;
COMMIT;Pros & Cons
Advantages : Strong consistency, simple reasoning.
Disadvantages : High lock‑wait overhead, reduced concurrency, risk of deadlocks.
Optimistic Lock
Typical Use Cases
User profile updates (avatar, nickname).
Counter increments (likes, view counts).
CAS‑based atomic updates.
Version‑Field Technique
Add a version column to the table.
Read the row together with its version.
Update only if the version matches; on success increment the version, otherwise retry.
UPDATE users SET name = 'new_name', version = version + 1
WHERE id = 1 AND version = old_version;Redis WATCH Example
WATCH balance:user1
balance = GET balance:user1
MULTI
SET balance:user1 balance - 100
EXEC # transaction fails if key was modifiedPros & Cons
Advantages : No lock‑wait latency, high throughput under low contention.
Disadvantages : Requires retry logic; performance degrades when conflicts become frequent.
Distributed Lock (Redis)
Typical Use Cases
Distributed scheduled tasks – avoid duplicate execution.
Global resource access – shared files or databases across services.
Cache‑breakdown protection – ensure only one request loads a hot key.
Lock Acquisition
SET lock:order_123 <uuid> NX PX 30000NX : Set only if the key does not exist, guaranteeing mutual exclusion.
PX 30000 : Expiration of 30 seconds to avoid deadlocks.
<uuid> : Unique token that identifies the lock owner and prevents accidental unlocks.
Atomic Unlock (Lua Script)
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
endPrecautions
Single‑point risk : A solitary Redis instance can become a failure point; consider the Redlock algorithm (subject to debate).
Clock drift : Time differences between Redis nodes may cause premature expiration.
Business timeout : If the client’s operation exceeds the lock TTL, the lock may be released while the client still assumes ownership, leading to duplicate processing.
Comparison Summary
Pessimistic Lock : Acquire lock first, then operate; suitable for high‑conflict, long‑critical‑section workloads on a single machine.
Optimistic Lock : Operate first, verify at commit; ideal for read‑heavy, low‑conflict, short‑critical‑section workloads.
Distributed Lock (Redis) : Provides mutual exclusion across nodes; incurs network overhead and requires careful handling of TTL and reliability.
Best‑Practice Recommendations
In single‑machine environments, prefer language‑level locks (e.g., Java synchronized, ReentrantLock) or database row locks.
In distributed deployments, use a dedicated distributed lock service such as Redis or Zookeeper.
Select the lock type based on conflict probability and consistency requirements: use pessimistic (or pessimistic‑style distributed) locks for strong‑consistency scenarios like inventory deduction, and optimistic locks for low‑conflict updates to avoid the performance cost of distributed coordination.
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.
Ray's Galactic Tech
Practice together, never alone. We cover programming languages, development tools, learning methods, and pitfall notes. We simplify complex topics, guiding you from beginner to advanced. Weekly practical content—let's grow together!
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.
