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

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

相关推荐
小马哥程序开发6 分钟前
[点赞收藏免费领取 · 项目源码]57105基于Spring Boot的充电桩管理系统的设计与实现
java·spring boot·源码·课程设计·毕设·大作业·课设
CS创新实验室37 分钟前
为什么三台机器就能选出一个“带头大哥“?——Raft 一致性算法,一次讲透
分布式·操作系统
本人手速666+2 小时前
企微开发API如何设计客户冻结状态?WeComApi 在删除、投诉和异常客户场景中的自动化边界
运维·分布式·自动化·企业微信·企微外部群开发·wecomapi·企业微信二次开发
卓怡学长2 小时前
w202springboot基于B_S架构的图书信息管理系统
java·spring boot·spring·intellij-idea
走到天涯海角2 小时前
用springBoot写几个简单的接口
java·spring boot·intellij-idea
xcl09253 小时前
西安同城货运系统源码开发实战 核心功能实现与部署全指南
java·spring boot
灯澜忆梦4 小时前
【RabbitMQ #4】 | Work 任务模型
分布式·rabbitmq
ym hyd 1114 小时前
慢性病精细化管理平台源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
程序猿乐锅4 小时前
【黑马点评 | 第七篇】Redis 分布式锁的两种实现
java·数据库·redis·分布式·spring·缓存
RuoyiOffice4 小时前
SpringBoot3+Vue3 低代码业务表单:从拖拽设计、独立建表到审批与数据查询
spring boot·vue3·数据建模·flowable·版本管理·低代码表单·ruoyi office