Understanding Redisson Distributed Lock Implementation in Java
This article explains how Redisson leverages Redis, Lua scripts, and Pub/Sub to implement a robust distributed lock in Java, covering lock characteristics, client creation, acquisition, renewal, and release mechanisms with code examples.
Introduction: Locks are used to control concurrent access to shared resources; in single‑service environments Java's synchronized or Lock implementations suffice, but in distributed systems they are inadequate, leading to the need for distributed locks.
Common distributed lock implementations include MySQL row‑level pessimistic lock, Redis (setnx+expire), and Zookeeper; this article focuses on Redis‑based Redisson and explains why it is recommended.
Characteristics of Distributed Locks
Mutual exclusion across threads and services, with considerations for spinning vs blocking.
Timeout to avoid stale locks.
Lease renewal (watchdog) because the exact execution time is unknown.
Re‑entrancy allowing the same thread to acquire the lock multiple times.
Ownership‑only release to prevent accidental unlocks.
Fair vs non‑fair acquisition policies.
Redisson implementation details:
Client creation
Each Redisson client generates a unique UUID used as an identifier in the lock metadata.
Lock acquisition
The lock method attempts to acquire the lock, subscribes to a Redis channel if it fails, and blocks until a release notification is received. The core steps are:
Try to acquire the lock (Lua script) and set lease time.
Subscribe to the lock channel using Redis Pub/Sub.
Cancel the subscription once the lock is obtained or the attempt is abandoned.
Key code snippets:
@Before
public void before() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://192.168.1.110:6379");
redissonClient = Redisson.create(config);
} @Test
public void multiLock() throws Exception {
RLock testLock = redissonClient.getLock("multi_lock");
int count = 5;
CountDownLatch latch = new CountDownLatch(count);
for (int i=1; i<=count; i++) {
new Thread(() -> {
try {
System.out.println("Thread " + Thread.currentThread().getName() + " trying to acquire lock");
testLock.lock();
System.out.println(String.format("Thread %s acquired lock, executing business...", Thread.currentThread().getName()));
TimeUnit.SECONDS.sleep(5);
System.out.println(String.format("Thread %s business done", Thread.currentThread().getName()));
latch.countDown();
} finally {
testLock.unlock();
System.out.println(String.format("Thread %s released lock", Thread.currentThread().getName()));
}
}, "t" + i).start();
}
latch.await();
System.out.println("Finished");
}Lock release
Unlocking runs a Lua script that decrements the re‑entrancy counter, removes the lock when the counter reaches zero, and publishes a release message to the channel.
Summary
Redisson achieves mutual exclusion, timeout, lease renewal, re‑entrancy, ownership‑only release, and supports fair/non‑fair policies by using Redis hash structures, Lua scripts, and Pub/Sub mechanisms.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.