Learn how to implement Redis-backed distributed locks to prevent race conditions in distributed systems.
- Common distributed lock scenarios
- Implementing locks with Redisson
- Preventing inventory oversell and duplicate processing
# From repository root
cd java-springboot/workshop-hub
# Start Redis + Postgres + Workshop
docker compose -f docker-compose.local.yml --profile infrastructure up -d
docker compose -f docker-compose.local.yml --profile workshop-3_distributed_locks up -d| Stage | What You Do |
|---|---|
1. / |
Reproduce the race-condition problem from the workshop home page |
2. /reentrant |
Learn why a reentrant lock is required for nested checkout calls |
3. /reentrant/implement |
Review the implementation guide before editing code |
4. /reentrant/editor or your IDE |
Update build.gradle.kts, src/main/resources/application.properties, and src/main/java/com/redis/workshop/locks/service/LockManager.java |
5. /reentrant/demo |
Rebuild from the Workshop Hub and verify the job, inventory, and checkout scenarios |
- Single-Runner Job - Only one worker runs a scheduled job
- Cache Stampede - Only one worker rebuilds cache
- Event Deduplication - Only one worker processes an event
- Single Import - Only one worker runs batch import
- Inventory Oversell - Prevent concurrent stock updates
The editable implementation path is:
build.gradle.ktssrc/main/resources/application.propertiessrc/main/java/com/redis/workshop/locks/service/LockManager.java
src/main/java/com/redis/workshop/locks/service/PurchaseService.java is included as a read-only review step so you can see how withLock() protects the inventory workflow.
workshop.lock.mode=redissonpublic <T> T withLock(String lockKey, Supplier<T> onAcquired, Supplier<T> onBusy) {
if (!isEnabled()) {
return onAcquired.get();
}
RLock lock = redissonClient.getLock(lockKey);
try {
boolean acquired = lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
if (acquired) {
return onAcquired.get();
} else {
return onBusy.get();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return onBusy.get();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}Open http://localhost:5540 and search for lock keys.
docker compose -f docker-compose.local.yml --profile workshop-3_distributed_locks down