How to Build a Robust Redis Distributed Lock with Spring AOP

This article explains why time‑consuming business operations need a distributed lock, walks through using Redis as a lock with Spring AOP, details the lock‑acquire, timeout, and renewal mechanisms, provides full code examples, testing steps, and best‑practice recommendations for reliable concurrency control in Java back‑end services.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
How to Build a Robust Redis Distributed Lock with Spring AOP

1. Business Background

Some business requests are time‑consuming and require locking to prevent concurrent operations that could corrupt data in the database.

2. Analysis Process

Redis is used as a distributed lock. The lock state is stored in Redis so that all JVMs in the cluster share the same lock information, enforcing an execution order and protecting data correctness.

Design steps

Create a custom annotation @interface to mark the method parameters that should be used as the lock key.

Add an AOP pointcut that scans for this annotation.

Define an @Aspect class that registers a bean and intercepts the targeted methods.

In the intercepted method, use ProceedingJoinPoint to run pjp.proceed() before and after the lock.

Acquire the lock before the method execution and delete the key after the task finishes.

Lock Acquisition

The implementation uses RedisTemplate.opsForValue().setIfAbsent to set a key only if it does not exist, assigning a random UUID as the value. After acquiring the lock, an expiration time is set so the lock is released automatically when it expires.

Timeout Issue

If the method execution exceeds the lock’s expiration time, the lock may be released early, allowing another thread to acquire it and causing concurrent modifications. For example, thread A holds the lock and sleeps for longer than the timeout; thread B then acquires the same lock, leading to inconsistent data.

Solution: Extend Lock

A scheduled thread pool ( ScheduledExecutorService) periodically scans the task queue and extends the lock’s expiration before it expires.

/**
 * Thread pool, each JVM maintains one thread to keep keyAliveTime, executing runnable periodically
 */
private static final ScheduledExecutorService SCHEDULER =
    new ScheduledThreadPoolExecutor(1,
        new BasicThreadFactory.Builder().namingPattern("redisLock-schedule-pool").daemon(true).build());

static {
    SCHEDULER.scheduleAtFixedRate(() -> {
        // iterate holderList, extend lock if needed
    }, 0, 2, TimeUnit.SECONDS);
}

3. Design Scheme

Based on the analysis, the following design was created:

Design diagram
Design diagram

Key steps:

Intercept the @RedisLock annotation and obtain necessary parameters.

Perform the lock operation.

Execute the renewal operation.

Finish the business logic and release the lock.

4. Implementation & Testing

In a controller method, the annotation is applied and a simulated long‑running request is created using Thread.sleep:

@GetMapping("/testRedisLock")
@RedisLockAnnotation(typeEnum = RedisLockTypeEnum.ONE, lockTime = 3)
public Book testRedisLock(@RequestParam("userId") Long userId) {
    try {
        log.info("Before sleep");
        Thread.sleep(10000);
        log.info("After sleep");
    } catch (Exception e) {
        log.info("has some error", e);
    }
    return null;
}

Test logs show the lock being acquired, the renewal attempts, and finally an InterruptedException when the retry limit is exceeded, confirming that the lock prevents concurrent modifications.

5. Summary

For time‑consuming operations that manipulate core data, a distributed lock using Redis protects against duplicate concurrent requests and ensures data integrity. The implementation demonstrates annotation‑driven AOP locking, lock renewal with a scheduled executor, and thread interruption for retry limits.

6. References

Original article: www.sevenyuan.cn/2020/04/04/redis/2020-04-04-annotation-redis-lock/

GitHub source: https://github.com/Vip-Augus/springboot-note/blob/master/src/main/java/cn/sevenyuan/demo/aop/lock/RedisLockAspect.java

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaconcurrencyredisdistributed-lockspring-aopScheduledExecutorService
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.