当前位置: 首页 > article >正文

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

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


http://www.kler.cn/a/471008.html

相关文章:

  • redis查看锁是否存在
  • 【数据库系统概论】数据库完整性与触发器--复习
  • Go Ebiten游戏库入门教程
  • 【NLP高频面题 - Transformer篇】什么是缩放点积注意力,为什么要除以根号d?
  • 开源人工智能模型框架:探索与实践
  • Leetcode打卡:不含特殊楼层的最大连续楼层数
  • 一文讲清楚PostgreSQL分区表
  • [openGauss 学废系列]-用户和模式的关系以及访问方式
  • Scala语言的语法
  • java实验6 J.U.C并发编程
  • jEasyUI 创建页脚摘要
  • Linux驱动开发 gpio_get_value读取输出io的电平返回值一直为0的问题
  • 咖啡馆系统|Java|SSM|JSP|
  • [Unity Shader] 【游戏开发】Unity基础光照1-光照模型原理
  • QT中如何限制 限制QLineEdit只能输入字母,或数字,或某个范围内数字等限制约束?
  • 26考研资料分享 百度网盘
  • Chrome 浏览器下载安装教程,保姆级教程
  • linux系统(ubuntu,uos等)连接鸿蒙next(mate60)设备
  • 【prometheus】Pushgateway安装和使用
  • Devart dotConnect发布全新版本,支持EF Core 9、完全兼容 .NET 9 等!