• 基于Zookeeper的瞬时节点实现分布式锁


    1、Zookeeper的数据结构

    二、zookeeper分布式锁原理

    二、zookeeper分布式锁代码实现

     1、maven依赖 

        (1)https://mvnrepository.com/   搜索 zookeeper

        (2)选择安装的对应版本

             

          (3) pom 文件 添加依赖

       

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

     2、核心类 ZkLock

        实现监控Watcher和自动关闭AutoCloseable 接口

      

    package com.example.distributezklock.lock;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.zookeeper.*;
    import org.apache.zookeeper.data.Stat;
    
    import java.io.IOException;
    import java.util.Collections;
    import java.util.List;
    
    @Slf4j
    public class ZkLock implements AutoCloseable, Watcher {
    
        private ZooKeeper zooKeeper;
        private String znode;
    
        public ZkLock() throws IOException {
            this.zooKeeper = new ZooKeeper("localhost:2181",
                    10000,this);
        }
    
        public boolean getLock(String businessCode) {
            try {
                //创建业务 根节点
                Stat stat = zooKeeper.exists("/" + businessCode, false);
                if (stat==null){
                    zooKeeper.create("/" + businessCode,businessCode.getBytes(),
                            ZooDefs.Ids.OPEN_ACL_UNSAFE,
                            CreateMode.PERSISTENT);
                }
    
                //创建瞬时有序节点  /order/order_00000001
                znode = zooKeeper.create("/" + businessCode + "/" + businessCode + "_", businessCode.getBytes(),
                        ZooDefs.Ids.OPEN_ACL_UNSAFE,
                        CreateMode.EPHEMERAL_SEQUENTIAL);
    
                //获取业务节点下 所有的子节点
                List<String> childrenNodes = zooKeeper.getChildren("/" + businessCode, false);
                //子节点排序
                Collections.sort(childrenNodes);
                //获取序号最小的(第一个)子节点
                String firstNode = childrenNodes.get(0);
                //如果创建的节点是第一个子节点,则获得锁
                if (znode.endsWith(firstNode)){
                    return true;
                }
                //不是第一个子节点,则监听前一个节点
                String lastNode = firstNode;
                for (String node:childrenNodes){
                    if (znode.endsWith(node)){
                        zooKeeper.exists("/"+businessCode+"/"+lastNode,true);
                        break;
                    }else {
                        lastNode = node;
                    }
                }
                synchronized (this){
                    wait();
                }
    
                return true;
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
    
    
    
    
        @Override
        public void close() throws Exception {
            zooKeeper.delete(znode,-1);
            zooKeeper.close();
            log.info("我已经释放了锁!");
        }
    
        @Override
        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeDeleted){
                synchronized (this){
                    notify();
                }
            }
        }
    }
    View Code

    3、Controller测试

      

    package com.example.distributezklock.controller;
    
    import com.example.distributezklock.lock.ZkLock;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.recipes.locks.InterProcessMutex;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    
    @RestController
    @Slf4j
    public class ZookeeperController {
        @Autowired
        private CuratorFramework client;
    
        @RequestMapping("zkLock")
        public String zookeeperLock(){
            log.info("我进入了方法!");
            try (ZkLock zkLock = new ZkLock()) {
                if (zkLock.getLock("order")){
                    log.info("我获得了锁");
                    Thread.sleep(10000);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("方法执行完成!");
            return "方法执行完成!";
        }
    
        @RequestMapping("curatorLock")
        public String curatorLock(){
            log.info("我进入了方法!");
            InterProcessMutex lock = new InterProcessMutex(client, "/order");
            try{
                if (lock.acquire(30, TimeUnit.SECONDS)){
                    log.info("我获得了锁!!");
                    Thread.sleep(10000);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    log.info("我释放了锁!!");
                    lock.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            log.info("方法执行完成!");
            return "方法执行完成!";
        }
    }
    View Code

    4、Test测试

    package com.example.distributezklock;
    
    import com.example.distributezklock.lock.ZkLock;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.recipes.locks.InterProcessMutex;
    import org.apache.curator.retry.ExponentialBackoffRetry;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class DistributeZkLockApplicationTests {
    
        @Test
        public void contextLoads() {
        }
    
    
        @Test
        public void testZkLock() throws Exception {
            ZkLock zkLock = new ZkLock();
            boolean lock = zkLock.getLock("order");
            log.info("获得锁的结果:"+lock);
    
            zkLock.close();
        }
    
    }
    View Code
  • 相关阅读:
    XML语法
    C/C++对MySQL操作
    HDU 3966 Aragorn's Story
    SPOJ 375 Query on a tree
    SPOJ 913 Query on a tree II
    SPOJ 6779 Can you answer these queries VII
    URAL 1471 Tree
    SPOJ 2798 Query on a tree again!
    POJ 3237 Tree
    SPOJ 4487 Can you answer these queries VI
  • 原文地址:https://www.cnblogs.com/callbin/p/14583930.html
Copyright © 2020-2023  润新知