#1
When multiple instances of an application run at the same time, they may try to update the same data simultaneously. This can cause race conditions, duplicated work, or inconsistent results.
Redis can solve this problem using distributed locking, ensuring that only one process performs a critical operation at a time.
This article explains how to implement Redis-based distributed locks in Spring Boot.

1. What Is Distributed Locking

Distributed locking ensures that only one instance of an application can execute a specific task.
Example scenario:
  • Multiple servers process the same scheduled job
  • Only one server should run the job
  • Redis lock prevents duplicate execution
Typical use cases:
  • Scheduled jobs
  • Payment processing
  • Inventory updates
  • Preventing duplicate requests

2. Simple Redis Lock Using RedisTemplate

A basic lock can be implemented using SETNX (set if not exists).
Example service:
@Service
public class RedisLockService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public boolean acquireLock(String lockKey) {
        Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, "LOCKED", Duration.ofSeconds(30));
        return Boolean.TRUE.equals(success);
    }
    
    public void releaseLock(String lockKey) {
        redisTemplate.delete(lockKey);
    }
}
Explanation:
  • setIfAbsent creates the lock only if it doesn't exist
  • TTL ensures the lock expires automatically

3. Using the Lock in a Service

Example usage:
public void processOrder() {
    String lockKey = "order_lock";
    
    if (!redisLockService.acquireLock(lockKey)) {
        System.out.println("Another process is already running");
        return;
    }

    try {
        // critical operation
        System.out.println("Processing order...");
    } finally {
        redisLockService.releaseLock(lockKey);
    }
}
This guarantees that only one instance executes the logic.

4. Handling Lock Expiration

Always define a TTL (time-to-live) for locks.
Example:
Duration.ofSeconds(30)
This prevents a situation where:
  • Application crashes
  • Lock is never released
The lock automatically expires.

5. Using Redisson for Production Locks

For production systems, a more reliable solution is Redisson, a Redis-based Java client with built-in distributed locks.
Example dependency (Maven):
<dependency>
 <groupId>org.redisson</groupId>
 <artifactId>redisson-spring-boot-starter</artifactId>
 <version>3.27.2</version>
</dependency>
Using Redisson lock:
@Autowired
private RedissonClient redissonClient;

public void executeTask() {

    RLock lock = redissonClient.getLock("taskLock");
    
    try {
        if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
            System.out.println("Task running...");
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
Benefits of Redisson:
  • Automatic lock renewal
  • Safe distributed locking
  • Easy integration with Spring Boot

6. Avoiding Common Mistakes

Common distributed lock problems:
❌ No expiration → permanent lock
❌ Releasing someone else's lock
❌ Locking large operations
Always:
✅ Use TTL
✅ Use unique lock keys
✅ Keep locked sections short

7. Real Example Use Case

Example: Prevent duplicate scheduled jobs.
@Scheduled(fixedRate = 60000)
public void runJob() {

    if(redisLockService.acquireLock("job_lock")) {
        try {
            System.out.println("Running scheduled job");
        } finally {
            redisLockService.releaseLock("job_lock");
        }
    }
}
Even if multiple app instances exist, only one will run the job.
#ads

image quote pre code