分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)

一  使用临时节点实现分布式锁

1.1 代码截图

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第1张图片

1.2 代码如下

由于zookeeper获取链接是一个耗时过程,这里可以在项目启动时,初始化链接,并且只初始化一次。借助于spring特性,代码实现如下:

package com.atguigu.distributed.lock.config;

import org.apache.zookeeper.*;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.CountDownLatch;

/**
 * @ClassName: ZkClient
 * @Description: TODO
 * @Author: admin
 * @Date: 2024/01/03 15:29:19 
 * @Version: V1.0
 **/
@Component
public class ZkClient {
    private static final String connectString = "192.168.43.4:2181";
    private static final String ROOT_PATH = "/d-zk";
    private ZooKeeper zooKeeper;
    @PostConstruct
    public void init(){
        //获取连接,项目启动时
        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            // 连接zookeeper服务器
            this.zooKeeper = new ZooKeeper(connectString, 30000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    Event.KeeperState state = event.getState();
                    if (Event.KeeperState.SyncConnected.equals(state)&&Event.EventType.None.equals(event.getType())){
                        System.out.println("获取链接成功!!");
                        countDownLatch.countDown();
                    }
                    else if(Event.KeeperState.Closed.equals(state)){
                        System.out.println("==================关闭链接成功!!");
                    }

                }
            });
            countDownLatch.await();
            // 创建分布式锁根节点
            if (this.zooKeeper.exists(ROOT_PATH, false) == null){
                //节点类型为持久化父节点
                this.zooKeeper.create(ROOT_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                System.out.println("创建分布式锁根节点。。。。。。。");
            }
        } catch (Exception e) {
            System.out.println("获取链接失败!");
            e.printStackTrace();
        }
    }

    @PreDestroy
    public void destroy(){
        try {
            if (zooKeeper != null){
                zooKeeper.close();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化zk分布式锁对象方法
     * @param lockName
     * @return
     */
    public ZkDistributedLock getZkDistributedLock(String lockName){
        return new ZkDistributedLock(zooKeeper, lockName);
    }
}

分布式锁实现类:

package com.atguigu.distributed.lock.config;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @ClassName: ZkDistributedLock
 * @Description: TODO
 * @Author: admin
 * @Date: 2024/01/03 15:32:05 
 * @Version: V1.0
 **/
public class ZkDistributedLock implements Lock {
    private static final String ROOT_PATH = "/d-zk";
    private String path;
    private ZooKeeper zooKeeper;
    public ZkDistributedLock(ZooKeeper zooKeeper, String lockName){
        this.zooKeeper = zooKeeper;
        this.path = ROOT_PATH + "/" + lockName;
    }
   /**
   * @author admin
   * @description      上锁
   * @date 2024/1/3 15:32
   * @param []
   * @return void
   */
    public void lock(){
     this.tryLock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        try {
            //创建临时节点
            zooKeeper.create(path, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            return true;
        } catch (Exception e) {
            // 。。。。。。。。。。。。。。。。。。。。。重试自旋。。。。。。。。。。。。。。。。。。。。。。。。
            try {
                Thread.sleep(200);
                this.tryLock();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    /**
    * @author admin
    * @description   解锁
    * @date 2024/1/3 15:33
    * @param []
    * @return void
    */
    public void unlock(){
        try {
            this.zooKeeper.delete(path, 0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

 3.修改service

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第2张图片

4.修改controller

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第3张图片

1.3 单笔测试

1.debug放问:http://localhost:9999/stock/deduct

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第4张图片

2.查看

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第5张图片

3.查看znode节点

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第6张图片

4.查看数据库

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第7张图片

1.4 nginx反向代理多节点

1.nginx配置

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第8张图片

2.启动nginx

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第9张图片

3.工程多服务端口启动

1.4 jemeter 压力测试

1.初始数据库

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第10张图片

2.设置jemter

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第11张图片

3.查看两个服务

端口:10087

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第12张图片

端口:10086 

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第13张图片

4.查看数据库

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第14张图片

5.查看 jemeter压测结果

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)_第15张图片

你可能感兴趣的:(分布式,zookeeper,分布式)