Distributed Lock Implementation with Redis and Redisson in Spring Boot
This article explains the concept, characteristics, and multiple implementation approaches of distributed locks, focusing on Redis‑based locks and the Redlock algorithm, and provides complete Java code examples using Spring Boot and Redisson for acquiring and releasing locks safely.
What is a Distributed Lock
In Java, traditional locks such as synchronized and Lock work only within a single JVM, but distributed systems require coordination across multiple servers, which leads to the need for distributed locks.
Definition
A distributed lock is a mechanism that ensures mutually exclusive access to a shared resource across different nodes in a distributed system, preventing data inconsistency.
Characteristics
Mutual exclusion – only one client can hold the lock at any time.
Lock timeout – similar to local locks, to avoid deadlocks.
High availability – lock acquisition and release must remain performant and resilient.
Supports blocking and non‑blocking operations, analogous to ReentrantLock 's lock, tryLock, and tryLock(long timeout).
Implementation Methods
Database lock
Redis‑based distributed lock
Zookeeper‑based distributed lock
For performance reasons, Redis is commonly used, and the Redlock algorithm can further improve reliability.
Code Example – Redis Lock
Lock acquisition uses the Redis atomic command: SET key value [NX|XX] [EX seconds|PX milliseconds] Parameter explanation:
EX seconds – expiration time in seconds.
PX milliseconds – expiration time in milliseconds.
NX – set only if the key does not exist.
XX – set only if the key already exists.
value – a globally unique identifier used to verify ownership when releasing.
/**
* Acquire lock
* @return true if lock acquired, false otherwise
*/
public boolean lock(String key, String value, long expireTime) {
key = prefixKey + key;
boolean lock = false;
try {
lock = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
lock = false;
}
if (lock) {
System.out.println(String.format("%s has obtained the lock, time: %s", Thread.currentThread().getName(), System.currentTimeMillis() / 1000));
}
return lock;
}Lock release should verify ownership, typically using a Lua script:
public boolean unLock(String key, String value) {
key = prefixKey + key;
Long result = -1L;
String luaScript =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
DefaultRedisScript<Long> redisScript = new DefaultRedisScript(luaScript, Long.class);
try {
result = (Long) redisTemplate.execute(redisScript, Lists.list(key), value);
} catch (Exception e) {
e.printStackTrace();
}
return result == 1 ? true : false;
}In a master‑slave setup, a race condition can occur if the master fails after granting a lock but before replicating it, leading to a "safe failure" scenario.
Redisson Implementation of Distributed Lock
Antirez proposed the Redlock algorithm to handle Redis node failures. The algorithm attempts to acquire the lock on multiple independent Redis instances; if a majority (N/2+1) succeed within the lock’s TTL, the lock is considered acquired.
Execution Steps
Client records the current time.
Client sends SET commands with NX and EX/PX to N Redis instances sequentially.
After all attempts, the client measures total elapsed time and checks two conditions:
At least a majority of instances granted the lock.
Total elapsed time is less than the lock’s TTL.
If both conditions are met, the client recalculates the remaining TTL and proceeds; otherwise it releases any acquired locks.
Redisson Code Example
Add the Redisson dependency:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.9.1</version>
</dependency>Configure a Sentinel‑based client:
Config config = new Config();
config.useSentinelServers()
.addSentinelAddress("127.0.0.1:6479", "127.0.0.1:6489")
.setMasterName("master")
.setPassword("password")
.setDatabase(0);
RedissonClient redisson = Redisson.create(config);Acquire and release the lock:
RLock lock = redisson.getLock("test_lock");
try {
boolean isLock = lock.tryLock();
if (isLock) {
// simulate business logic
doBusiness();
}
} catch (Exception e) {
// handle exception
} finally {
lock.unlock();
}Project Source Code
https://github.com/aalansehaiyang/spring-boot-bulking
Module: spring-boot-bulking-redis-lockFor further reading, the article also recommends related posts on Redis cache design, architecture principles, and Spring Boot Kafka integration.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
