Distributed Locking
True distributed locking across multiple servers using Couchbase's native locking mechanism.
True distributed locking across multiple servers using Couchbase's native locking mechanism.
🎯 What is Distributed Locking?
Distributed locking ensures that only one process across your entire server cluster can execute a critical section of code at a time. This is essential for:
💰 Financial transactions - Prevent double-charging or race conditions
📦 Inventory updates - Avoid overselling products
🔄 Batch processing - Ensure only one server runs the job
🎫 Ticket sales - Prevent double-booking
👤 User account updates - Serialize concurrent modifications
🚀 Quick Start
Component Usage (Recommended)
<bx:CouchbaseLock
name="user-#userId#-update"
cache="default"
timeout="5"
expires="30">
// Critical section - only one request at a time
user = getUser(userId);
user.balance += amount;
saveUser(user);
</bx:CouchbaseLock>BIF with Callback
BIF Manual Mode
📖 How It Works
Lock Mechanism
Couchbase provides distributed locking using its getAndLock() API:
Lock Document Created: A special document with prefix
__lock:{cacheName}:{lockName}Exclusive Access: Couchbase ensures only one server can lock the document
Automatic Expiry: Lock expires after specified duration (max 30 seconds)
CAS-Based Unlock: Unlock requires the correct CAS value from acquisition
Lock Key Format
Example: __lock:sessionCache:user-123-update
🎨 Usage Patterns
Pattern 1: Component for Simple Cases
Best for straightforward critical sections with no complex logic:
Pattern 2: Callback for Return Values
When you need to return a value from the locked section:
Pattern 3: Manual for Complex Control
When you need fine-grained control over lock lifecycle:
💡 Real-World Examples
Example 1: Prevent Double-Charging
Example 2: Inventory Management
Example 3: Scheduled Job Coordination
Example 4: Sequential Document Processing
Example 5: Rate Limiting with Locks
⚙️ Configuration
Component Attributes
name
String
Yes
-
Unique lock name across cluster
cache
String
Yes
-
Couchbase cache name
timeout
Integer
No
5
Seconds to wait for lock
expires
Integer
No
30
Lock expiration (max 30)
throwOnTimeout
Boolean
No
true
Throw exception on timeout
bypass
Boolean
No
false
Skip locking (for testing)
BIF Parameters
couchbaseLock():
cacheName(String, required) - Cache namename(String, required) - Lock nametimeout(Integer, optional, default: 5) - Acquisition timeout in secondsexpires(Integer, optional, default: 30) - Lock expiration in secondscallback(Function, optional) - Function to execute with lock heldthrowOnTimeout(Boolean, optional, default: true) - Throw on timeout
couchbaseUnlock():
cacheName(String, required) - Cache namename(String, required) - Lock namecas(Long, required) - CAS value from lock acquisition
⚠️ Important Limitations
30 Second Maximum
Couchbase limits getAndLock() to 30 seconds maximum:
For operations longer than 30 seconds, consider:
Breaking into smaller locked operations
Using a different synchronization approach
Implementing a heartbeat/renewal pattern
Lock Expiration
Locks automatically expire after the specified duration. If your operation takes longer, the lock will be released:
Solution: Set expires longer than your operation needs.
🎭 Best Practices
✅ DO
Use descriptive lock names:
Keep critical sections short:
Always use try/finally with manual locks:
Set appropriate timeouts:
❌ DON'T
Don't use locks for caching:
Don't nest locks (deadlock risk):
Don't hold locks during I/O:
🔍 Testing
Bypass Mode
Use bypass=true for testing without actual locking:
Mock Scenarios
Test lock behavior with short timeouts:
🐛 Troubleshooting
Lock Timeout Errors
Problem: Failed to acquire lock within X seconds
Solutions:
Increase
timeoutparameterEnsure locks are being released properly
Check for deadlocks or stuck processes
Verify lock expiration is appropriate
Stale Locks
Problem: Lock seems permanently held
Cause: Locks auto-expire after expires seconds
Solution:
Wait for expiration (max 30 seconds)
Or manually remove lock document:
Performance Impact
Problem: Locking adds latency
Solutions:
Reduce lock duration - keep critical sections minimal
Use shorter timeouts for better responsiveness
Consider if locking is really needed
Cache frequently-accessed data outside locks
📊 Monitoring
Monitor lock usage:
🔗 Related Functions
couchbaseLock - Acquire lock
couchbaseUnlock - Release lock
CouchbaseLock Component - Component reference
📚 See Also
Code Usage - Cache operations
Troubleshooting - Common issues
Last updated
Was this helpful?
