springboot zookeeper 实现分布式锁

首先这里用的springboot版本为2.2.2 ,zookeeper用的版本是 3.4.14 ,开发工具用的是java 开发神奇idea

这里的pom的代码如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.2.2.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.ext</groupId>
   <artifactId>demozk</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>demozk</name>
   <description>Demo project for Spring Boot</description>

   <properties>
      <java.version>11</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      
      <dependency>
         <groupId>org.apache.curator</groupId>
         <artifactId>curator-recipes</artifactId>
         <version>4.0.0</version>
         <exclusions>
            <exclusion>
               <groupId>org.apache.zookeeper</groupId>
               <artifactId>zookeeper</artifactId>
            </exclusion>
         </exclusions>
      </dependency>

      <dependency>
         <groupId>org.apache.zookeeper</groupId>
         <artifactId>zookeeper</artifactId>
         <version>3.4.14</version>
      </dependency>



      <!-- https://mvnrepository.com/artifact/io.mateu/lombok -->
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <scope>provided</scope>
      </dependency>


      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
         <exclusions>
            <exclusion>
               <groupId>org.junit.vintage</groupId>
               <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
         </exclusions>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-tx</artifactId>
         <version>5.2.3.RELEASE</version>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

 

要说明的是  curator 用的是4.0 的版本所以要去掉自身的zookeeper 因为它自己的版本是3.5的,同时要加上我们自己用的3.4的版本,否则会报错的。

监听代码如下

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.curator.framework.api.CuratorEventType;
import org.apache.zookeeper.WatchedEvent;


public class MyCuratorListener implements CuratorListener {
    @Override
    public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
        CuratorEventType type = event.getType();
        if(type == CuratorEventType.WATCHED){
            WatchedEvent watchedEvent = event.getWatchedEvent();
            String path = watchedEvent.getPath();
            System.out.println(watchedEvent.getType()+" -- "+ path);
            // 重新设置改节点监听
            if(null != path)
                client.checkExists().watched().forPath(path);
        }
    }
}

 

zookeeper的配置代码如下:

import com.ext.demozk.common.MyCuratorListener;
import org.springframework.context.annotation.Configuration;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ZookeeperConfig {
    /**
     * Curator Apache
     * 供的个访问Zookeeper的工具包,封装了这些低级别操作同时也提供一些高级服务,比如分布式锁、领导选取
     * @return
     */
    @Bean
    public CuratorFramework curatorFramework(){
        // ExponentialBackoffRetry是种重连策略,每次重连的间隔会越来越长,1000毫秒是初始化的间隔时间,3代表尝试重连次数。
        ExponentialBackoffRetry retry = new ExponentialBackoffRetry(1000, 3);
        // 创建client
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", retry);
        // 添加watched 监听器
        curatorFramework.getCuratorListenable().addListener(new MyCuratorListener());
        curatorFramework.start();
        return curatorFramework;
    }

}

 

zookeeper锁的代码如下

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;


@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class CuratorLockService {
    @Autowired
    private CuratorFramework client;

    /**
     * 分布式锁的初始路径
     */
    private String lockPath = "/lock/test";


    public void lockTest(String value) throws Exception {
        lockPath = lockPath + "/" + value;
        log.info("尝试执行业务" + value);

        // 创建分布式锁
        InterProcessMutex lock = new InterProcessMutex(client, lockPath);
        try {
            // 获取锁资源
            if (lock.acquire(10, TimeUnit.HOURS)) {
                log.info("业务逻辑模拟,耗时25s");
                Thread.sleep(25000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                lock.release();
                log.info("释放锁资源");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

}

 

controller层调用 service层的代码如下:

import com.ext.demozk.entity.InvokeResult;
import com.ext.demozk.service.CuratorLockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class testController {

    @Autowired
    CuratorLockService lockService;

    @GetMapping("lock/test")
    public String lock(String value) throws Exception{
        lockService.lockTest(value);
        return  "success";
    }
}

 

在使用的过程中出现了一些问题如下:

org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for /lock/test/11/_c_6fe4fe88-fcfe-490c-bafe-bafe7e0cb4bd-lock-
    at org.apache.zookeeper.KeeperException.create(KeeperException.java:103) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
    at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
    at org.apache.zookeeper.ZooKeeper.create(ZooKeeper.java:1297) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
    at org.apache.curator.framework.imps.CreateBuilderImpl$17.call(CreateBuilderImpl.java:1075) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.imps.CreateBuilderImpl$17.call(CreateBuilderImpl.java:1058) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.connection.StandardConnectionHandlingPolicy.callWithRetry(StandardConnectionHandlingPolicy.java:67) ~[curator-client-3.3.0.jar:na]
    at org.apache.curator.RetryLoop.callWithRetry(RetryLoop.java:100) ~[curator-client-3.3.0.jar:na]
    at org.apache.curator.framework.imps.CreateBuilderImpl.pathInForeground(CreateBuilderImpl.java:1055) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.imps.CreateBuilderImpl.protectedPathInForeground(CreateBuilderImpl.java:524) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:514) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:492) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:44) ~[curator-framework-3.3.0.jar:3.3.0]
    at org.apache.curator.framework.recipes.locks.StandardLockInternalsDriver.createsTheLock(StandardLockInternalsDriver.java:54) ~[curator-recipes-3.3.0.jar:na]
    at org.apache.curator.framework.recipes.locks.LockInternals.attemptLock(LockInternals.java:218) ~[curator-recipes-3.3.0.jar:na]
    at org.apache.curator.framework.recipes.locks.InterProcessMutex.internalLock(InterProcessMutex.java:232) ~[curator-recipes-3.3.0.jar:na]
    at org.apache.curator.framework.recipes.locks.InterProcessMutex.acquire(InterProcessMutex.java:108) ~[curator-recipes-3.3.0.jar:na]
    at com.ext.demozk.service.CuratorLockService.lockTest(CuratorLockService.java:36) ~[classes/:na]
    at com.ext.demozk.controller.testController.lock(testController.java:17) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_221]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_221]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_221]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_221]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]

最终发现的问题是zookeeper 的版本不一致导致错误,pom文件改为下面的 吧curator-recipes 3.0版本改为下面的4.0版本

 

<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-recipes</artifactId>
   <version>4.0.0</version>
   <exclusions>
      <exclusion>
         <groupId>org.apache.zookeeper</groupId>
         <artifactId>zookeeper</artifactId>
      </exclusion>
   </exclusions>
</dependency>

<dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.14</version>
</dependency>

然后就解决问题了,欢迎大家批评指正。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值