在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 项目中实现高效、可靠的分布式锁。

相关推荐
布局呆星5 小时前
SpringBoot 基础入门
java·spring boot·spring
不懂的浪漫6 小时前
mqtt-plus 架构解析(六):多 Broker 管理,如何让一个应用同时连接多个 MQTT 服务
spring boot·分布式·物联网·mqtt·架构
不懂的浪漫6 小时前
mqtt-plus 架构解析(十):从内部项目到开源框架,mqtt-plus 的抽取过程与决策
spring boot·mqtt·架构·开源
一 乐10 小时前
酒店预订|基于springboot + vue酒店预订系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·酒店预订系统
格鸰爱童话11 小时前
向AI学习项目技能(六)
java·人工智能·spring boot·python·学习
H_老邪11 小时前
spring boot 学习之路-1.0
spring boot·后端·学习
Flittly12 小时前
【SpringAIAlibaba新手村系列】(18)Agent 智能体与今日菜单应用
java·spring boot·agent
Andya_net12 小时前
Java | 基于 Feign 流式传输操作SFTP文件传输
java·开发语言·spring boot
小夏子_riotous13 小时前
openstack的使用——5. Swift服务的基本使用
linux·运维·开发语言·分布式·云计算·openstack·swift
成为大佬先秃头13 小时前
开放标准(RFC 7519):JSON Web Token (JWT)
spring boot·后端·json·jwt