zookeeper的分布式锁(公平锁和非公平锁)

zookeeper中锁分两种:公平锁和非公平锁
公平锁就是排队,一个一个来
非公平锁就是谁抢到谁得

zookeeper公平锁:
zookeeper公平锁是基于它的临时有序节点实现的,当并发访问某一个接口后,会在zookeeper中创建一个临时有序节点,并且这些节点名称都是一样的,当时zookeeper会在名称后加上一个序号,每一个节点只监听比他序号小的,当节点发现他是最小 的就会获取锁资源,如果不是最小的就会一直在那等着。

zookeeper分布式锁和redis分布式锁的区别:
redis分布式锁是基于key实现的,并且有超时时间问题的发生
zookeeper分布式锁基于临时节点实现的,不会有超时问题发生,一旦超时直接报错,断开连接后会清除临时节点信息


zookeeper公平锁具体案例: springboot写的
步骤一:在pom.xml文件中改成2.0.6版本,然后导入依赖

<?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.0.6.RELEASE</version><!--改成了2.0.6-->
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.qf</groupId>
	<artifactId>zookeeper</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>zookeeper</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

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

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

		<!--zookeeper客户端-->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>4.0.1</version>

		</dependency>

		<!--zkclient-->

		<dependency>
			<groupId>com.101tec</groupId>
			<artifactId>zkclient</artifactId>
			<version>0.10</version>
		</dependency>
	</dependencies>

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

</project>

步骤二:创建连接zookeeper的工具类

本案例将该类命名为:ConnectionZK

package com.qf.zookeeper;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Test;

import java.util.List;

public class ConnectionZK {

    //这里是一个工具类方法,专门获得连接对象,用于调用各种方法
    public static CuratorFramework  getCf(){
      //指定重试策略。每隔四秒重试一次,一共重试2次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 2);//每隔四秒触发一次,重试两次

        //连接zookeeper的客户端对象
        CuratorFramework cf = CuratorFrameworkFactory.builder()
                .connectString("192.168.22.131:2181,192.168.22.131:2182,192.168.22.131:2183")//连接zookeeper集群中的所有zookeeper。格式:   zookeeper的ip:zookeeper的端口号
                .connectionTimeoutMs(6000)//超时时间,6秒
                .retryPolicy(retryPolicy)//设置超时处理策略
                .build();
        //开启连接
        cf.start();
        return cf;//返回zookeeper连接对象,用于节点和数据的创建
    }


    
}

步骤三:在controller创建使用锁的测试类

本案例将该类命名为:LookController

package com.qf.controller;

import com.qf.zookeeper.ConnectionZK;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.concurrent.TimeUnit;
@Controller
@RequestMapping("/lock")
public class LookController {
    private static  int i=10000;
    private static  int j=0;
    @RequestMapping("/man-a-lock")
    @ResponseBody
    public String manALock(){
    //获取客户端
        CuratorFramework cf = ConnectionZK.getCf();

        //创建zookeeper实现的公平锁.公平锁是zookeeper自带的
        InterProcessMutex lock = new InterProcessMutex(cf, "/man-a-lock");//第一个参数是连接zookeeper的对象,第二个是指定在那个节点下面创建临时有序节点,没创建也行


        try{//zookeeper非公平锁才加trycache
            //lock.acquire //慢慢排队,无论多慢都排队
        //加锁,未解锁时并发会出现i和j加起来不等于10000
            if (lock.acquire(1, TimeUnit.SECONDS)){ //慢慢排队,超过一秒就不排了

            Thread.sleep(10);
            i--;

            j++;



        //解锁
            lock.release();
            }else {
                System.out.println("用户太多,被挤爆了!!");
            }

        } catch (Exception e) {
            System.out.println("没有获取到锁资源");
        }finally {
            cf.close();//关闭客户端,执行完,必须关闭
        }

        return "i="+i+";j="+j;
    }

}

公平锁案例结构图:
在这里插入图片描述


zookeeper非公平锁:
使用的是临时节点。公平锁使用的是临时有序节点
用户想获取到锁资源,用户就尝试创建指定的一个节点,如果节点存在,说明锁资源正在占用,直接抛出异常,try-catch中给用户提示,如果创建节点成功,线程成功的获取到了锁资源.
如果出现了死锁?
因为创建的时临时节点,如果出现异常,那么客户端自动断开连接,临时节点自动被删除.

zookeeper非公平锁具体案例:

步骤一:在pom.xml文件中修改版本并导入依赖

<?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.0.6.RELEASE</version><!--改成了2.0.6-->
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.qf</groupId>
	<artifactId>zookeeper</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>zookeeper</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

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

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

		<!--zookeeper客户端-->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>4.0.1</version>

		</dependency>

		<!--zkclient-->

		<dependency>
			<groupId>com.101tec</groupId>
			<artifactId>zkclient</artifactId>
			<version>0.10</version>
		</dependency>
	</dependencies>

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

</project>

步骤二:创建获取zookeeper连接对象的工具类
将该类命名为:ConnectionZK

package com.qf.zookeeper;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Test;

import java.util.List;

public class ConnectionZK {

    //这里是一个工具类方法,专门获得连接对象,用于调用各种方法
    public static CuratorFramework  getCf(){
      //指定重试策略。每隔四秒重试一次,一共重试2次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(4000, 2);//每隔四秒触发一次,重试两次

        //连接zookeeper的客户端对象
        CuratorFramework cf = CuratorFrameworkFactory.builder()
                .connectString("192.168.22.131:2181,192.168.22.131:2182,192.168.22.131:2183")//连接zookeeper集群中的所有zookeeper。格式:   zookeeper的ip:zookeeper的端口号
                .connectionTimeoutMs(6000)//超时时间,6秒
                .retryPolicy(retryPolicy)//设置超时处理策略
                .build();
        //开启连接
        cf.start();
        return cf;//返回zookeeper连接对象,用于节点和数据的创建
    }



}

步骤三:创建使用非公平锁的类
本案例将该类命名为:LookController

package com.qf.controller;

import com.qf.zookeeper.ConnectionZK;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.zookeeper.CreateMode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.concurrent.TimeUnit;
@Controller
@RequestMapping("/lock")
public class LookController {
    private static  int i=10000;
    private static  int j=0;



    @RequestMapping("/not-man-a-lock")
    @ResponseBody
    public String notManLock(){
        //获取连接对象
        CuratorFramework cf=ConnectionZK.getCf();
        //声明锁节点名称
        String lockName = "/not-man-a-lock";//节点必须写/

        //创建临时节点
        try {
            //开锁
            cf.create().withMode(CreateMode.EPHEMERAL).forPath(lockName);//PERSISTENT持久节点、PERSISTENT_SEQUENTIAL持久有序节点、EPHEMERAL临时节点、EPHEMERAL_SEQUENTIAL临时有序节点
            //获取到锁资源,操作
            i--;
            j++;
            //解锁
            cf.delete().forPath(lockName);
        } catch (Exception e) {
            System.out.println("没有获取到锁资源!!!!!");
        }finally {
            cf.close();
        }

        return "i="+i+";j="+j;

    }

}

非公平锁的结构图:
在这里插入图片描述

非公平锁和公平锁的启动类没变,springboot会自动扫描controller注解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值