在Spring Boot项目中使用Zookeeper和Curator实现高效、可靠的分布式锁

要在 Spring Boot 项目中使用 Zookeeper 和 Curator 实现高效、可靠的分布式锁,可以参考以下步骤和优化建议:

1. 引入依赖

pom.xml 中添加 Curator 和 Zookeeper 相关依赖:

xml 复制代码
<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 连接字符串:

yaml 复制代码
zookeeper:
  connect-string: localhost:2181

3. 配置 Curator 客户端

创建一个配置类来初始化 Curator 客户端:

java 复制代码
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. 实现分布式锁服务

创建一个服务类来封装分布式锁的获取和释放逻辑,并进行一些优化:

java 复制代码
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 并调用相应方法:

java 复制代码
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_RETRIESRETRY_INTERVAL_MS,以提高获取锁的成功率。
  • 异常处理:在获取和释放锁的过程中,对可能出现的异常进行详细的日志记录,便于排查问题。
  • 锁粒度:根据业务需求合理设置锁的粒度,避免锁的范围过大影响系统性能。
  • 锁超时:设置合理的锁超时时间,防止因锁长时间未释放而导致的死锁问题。

通过以上步骤和优化建议,可以在 Spring Boot 项目中实现高效、可靠的分布式锁。

相关推荐
Rover.x19 分钟前
Netty基于SpringBoot实现WebSocket
spring boot·后端·websocket
中国胖子风清扬1 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
Java水解2 小时前
【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
spring boot·后端
哈哈老师啊2 小时前
Springboot校园订餐管理系统k2pr7(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
JIngJaneIL2 小时前
基于java+ vue学生选课系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
残花月伴2 小时前
天机学堂-day4(高并发优化方案)
java·spring boot·后端
阿拉斯攀登3 小时前
Spring Boot ——入门与实战
spring boot·springboot
Wang's Blog3 小时前
RabbitMQ: 实现高效消息监听之从基础到自动配置
分布式·rabbitmq
JIngJaneIL3 小时前
基于java+ vue建筑材料管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
一 乐3 小时前
办公系统|基于springboot + vueOA办公管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring