在Spring Boot项目中使用Zookeeper和Curator实现高效、可靠的分布式锁
要在 Spring Boot 项目中使用 Zookeeper 和 Curator 实现高效、可靠的分布式锁,可以参考以下步骤和优化建议:
1. 引入依赖
在 pom.xml
中添加 Curator 和 Zookeeper 相关依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.0</version>
</dependency>
</dependencies>
2. 配置 Zookeeper 连接
在 application.yml
中配置 Zookeeper 连接字符串:
zookeeper:
connect-string: localhost:2181
3. 配置 Curator 客户端
创建一个配置类来初始化 Curator 客户端:
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZookeeperConfig {
@Value("${zookeeper.connect-string}")
private String connectString;
@Bean(initMethod = "start", destroyMethod = "close")
public CuratorFramework curatorFramework() {
return CuratorFrameworkFactory.builder()
.connectString(connectString)
.sessionTimeoutMs(5000)
.retryPolicy(new RetryNTimes(3, 5000))
.build();
}
}
4. 实现分布式锁服务
创建一个服务类来封装分布式锁的获取和释放逻辑,并进行一些优化:
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class DistributedLockService {
private static final Logger logger = LoggerFactory.getLogger(DistributedLockService.class);
@Autowired
private CuratorFramework curatorFramework;
// 重试获取锁的次数
private static final int MAX_RETRIES = 3;
// 每次重试的间隔时间
private static final int RETRY_INTERVAL_MS = 1000;
// 获取分布式锁
public boolean acquireLock(String lockPath, int timeout, TimeUnit timeUnit) {
InterProcessMutex lock = new InterProcessMutex(curatorFramework, lockPath);
for (int i = 0; i < MAX_RETRIES; i++) {
try {
if (lock.acquire(timeout, timeUnit)) {
logger.info("成功获取分布式锁,锁路径: {}", lockPath);
return true;
}
} catch (Exception e) {
logger.error("获取分布式锁失败,尝试重试,锁路径: {}", lockPath, e);
}
try {
TimeUnit.MILLISECONDS.sleep(RETRY_INTERVAL_MS);
} catch (InterruptedException e) {
logger.error("重试间隔被中断", e);
Thread.currentThread().interrupt();
}
}
logger.warn("经过多次重试仍无法获取分布式锁,锁路径: {}", lockPath);
return false;
}
// 释放分布式锁
public void releaseLock(String lockPath) {
InterProcessMutex lock = new InterProcessMutex(curatorFramework, lockPath);
try {
lock.release();
logger.info("成功释放分布式锁,锁路径: {}", lockPath);
} catch (Exception e) {
logger.error("释放分布式锁失败,锁路径: {}", lockPath, e);
}
}
}
5. 使用分布式锁
在需要使用分布式锁的地方注入 DistributedLockService
并调用相应方法:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DistributedLockUsageController {
@Autowired
private DistributedLockService distributedLockService;
@GetMapping("/protected-operation")
public String protectedOperation(@RequestParam String lockPath) {
int timeout = 10;
TimeUnit timeUnit = TimeUnit.SECONDS;
if (distributedLockService.acquireLock(lockPath, timeout, timeUnit)) {
try {
// 这里放置需要同步执行的业务逻辑
return "成功获取锁并执行了受保护的操作";
} finally {
distributedLockService.releaseLock(lockPath);
}
} else {
return "无法获取锁,操作被拒绝";
}
}
}
优化建议
- 重试机制:在获取锁时增加重试机制,如上述代码中的
MAX_RETRIES
和RETRY_INTERVAL_MS
,以提高获取锁的成功率。 - 异常处理:在获取和释放锁的过程中,对可能出现的异常进行详细的日志记录,便于排查问题。
- 锁粒度:根据业务需求合理设置锁的粒度,避免锁的范围过大影响系统性能。
- 锁超时:设置合理的锁超时时间,防止因锁长时间未释放而导致的死锁问题。
通过以上步骤和优化建议,可以在 Spring Boot 项目中实现高效、可靠的分布式锁。