Pro Tips — Redis Distributed Lock (Redisson) for Concurrency Control
In horizontally scaled (Scale-Out) server environments, Java's synchronized keyword or ReentrantLock — both single-JVM constructs — are completely ineffective. When different physical servers concurrently access the same DB record, you need a Redis Distributed Lock to enforce mutual exclusion.
1. Distributed Locking with Redisson
The Redisson library provides a Java-friendly distributed lock built on top of Redis. When tryLock() is called, only the first server acquires the lock — others wait until it's released.
implementation 'org.redisson:redisson-spring-boot-starter:3.29.0'
@Service
@RequiredArgsConstructor
@Slf4j
public class CouponService {
private final RedissonClient redissonClient;
private final CouponRepository couponRepository;
public void issueCoupon(Long userId) {
String lockKey = "coupon:issue:lock:" + userId;
RLock lock = redissonClient.getLock(lockKey);
// Try to acquire for up to 5 seconds; hold for max 3 seconds then auto-release
boolean acquired = false;
try {
acquired = lock.tryLock(5, 3, TimeUnit.SECONDS);
if (!acquired) {
throw new IllegalStateException("Another request is in progress. Please try again shortly.");
}
// Only the thread holding the lock enters here
Coupon coupon = couponRepository.findAvailable()
.orElseThrow(() -> new IllegalStateException("All coupons have been claimed."));
coupon.assignTo(userId);
couponRepository.save(coupon);
log.info("Coupon issued successfully: userId={}", userId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// Always release in finally — guaranteed even if an exception occurs
if (acquired && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
2. Redis Lock vs DB Pessimistic Lock Comparison
| Criterion | Redis Distributed Lock (Redisson) | DB Pessimistic Lock (@Lock(PESSIMISTIC_WRITE)) |
|---|---|---|
| Performance | Very fast (in-memory) | Slow (holds DB connection, row-level lock) |
| Infrastructure | Requires Redis server | No additional infrastructure needed |
| On failure | Redis failure = lock unavailable | DB failure = lock down too |
| Best for | High-traffic concurrency control | Small-scale business consistency guarantees |
tip
If the lock TTL is too short, the lock may expire before business logic completes — reintroducing concurrency bugs. Set TTL at at least 3x the expected processing time, and consider Redisson's watchdog feature which automatically extends TTL while the lock is held.