Implement Distributed Locks with Spring Integration: Redis & Zookeeper Guide
Learn how to implement distributed locks in Spring-based applications using Spring Integration, covering Redlock, Apache Curator alternatives, and detailed step-by-step examples for Redis and Zookeeper backends, including configuration, code snippets, testing procedures, and troubleshooting tips for reliable lock management.
Overview
When people talk about distributed locks, two common solutions are Redisson (Redlock algorithm) and Apache Curator (Zookeeper temporary sequential nodes). This article introduces a third approach using Spring Integration, which I recommend.
Spring Integration provides lightweight messaging for Spring applications and underlies Spring Cloud Stream. It offers a unified API for global locks backed by Gemfire, JDBC, Redis, and Zookeeper, allowing the same code to switch storage without changes.
Key Methods
lock(): Acquires the lock; blocks if already held.
lockInterruptibly(): Acquires the lock unless the thread is interrupted.
tryLock(): Attempts to acquire the lock only if it is free; returns true on success.
tryLock(long time, TimeUnit unit): Tries to acquire the lock within the given waiting time; returns true on success.
unlock(): Releases the lock.
Practical Example
Redis Implementation
Add Maven dependencies for
spring-boot-starter-integration,
spring-integration-redis, and
spring-boot-starter-data-redis.
Configure Redis connection in
application.yml.
Create a @Configuration class that defines a
RedisLockRegistrybean.
Write a @RestController with an endpoint
/lock/redisthat obtains a lock from the registry, tries to lock for 3 seconds, logs the result, sleeps for 5 seconds, and finally unlocks.
Run multiple instances and call the endpoint; only one instance obtains the lock, demonstrating distributed locking.
Note: When using newer Spring Boot versions, ensure Redis 4.x is used; otherwise the unlock() operation may fail because the UNLINK command is unsupported.
<code>2020-05-14 11:30:24,781 WARN RedisLockRegistry:339 - The UNLINK command has failed (not supported on the Redis server?); falling back to the regular DELETE command
org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'UNLINK'
</code>Zookeeper Implementation
Add Maven dependencies for
spring-boot-starter-integrationand
spring-integration-zookeeper.
Configure Zookeeper connection in
application.yml.
Create a @Configuration class that defines a
CuratorFrameworkFactoryBeanand a
ZookeeperLockRegistrybean.
Write a @RestController with an endpoint
/lock/zookeeperthat obtains a lock from the Zookeeper registry, tries to lock for 3 seconds, logs, sleeps, and finally unlocks.
Run multiple instances and call the endpoint; only one instance acquires the lock, confirming the distributed lock works.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.