zookeeper实现分布式锁

背景:这是一个老生长谈的问题了,能够用redis、数据库、zookeeper。这里今天就用zookeeper来实现下。java

 

这个版本也是参考CSDN公众号来实现的,原理很简单:只要利用apache curator封装后的client直接链接zk server,获取锁就好了。步骤以下:git

一、安装好zk3.5单机版redis

二、配置一下pom(国外的maven仓库链接不上,配置阿里云的maven仓库数据库

三、运行java代码apache

package hello;

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;

/**
 * Created by Germmy on 2017/11/4.
 */
public class MyClient {

    public static void main(String[] args) {
        try {
            //建立zookeeper的客户端
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.92.134:2181", retryPolicy);
            client.start();

            //建立分布式锁, 锁空间的根节点路径为/curator/lock
            InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
            mutex.acquire();
            //得到了锁, 进行业务流程
            System.out.println("Enter mutex");
            //完成业务流程, 释放锁
            mutex.release();

            //关闭客户端
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

注意:apche curator必须用在3.5版本上的zk,不然会报unimplement异常,curator官方说兼容3.4.X,但实际上呵呵了windows

 

四、编写一个客户端来试,这个客户端就是负责将它一个变量自增,那么在多个线程全在操做这个客户端时,是否会发生线程安全问题呢?安全

4.一、先用非线程安全的客户端试下,源码以下:maven

package hello;

/**
 * Created by Germmy on 2017/11/5.
 */
public class MyClientNotSafe implements  Runnable {
    public static int num=0;
    public void run() {
        num++;
        System.out.println("当前线程ID是:"+Thread.currentThread().getId()+",数字是:"+num);
    }
}

 

线程池的源码以下:分布式

@Test
    public  void testNumPlusNoSafe(){
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++){
            executorService.execute(new MyClientNotSafe());
        }
        executorService.shutdown();
    }

输出结果以下:测试

发现有2个结果全是2,线程不安全。

 

4.二、用分布式锁的客户端锁试下,客户端源码以下:

package hello;

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;

/**
 * Created by Germmy on 2017/11/4.
 */
public class MyClient implements  Runnable {

    public static int num=0;

    public void run(){
        System.out.println("进入了MyClient1...");
        try {
            System.out.println("进入了MyClient2...");
            //建立zookeeper的客户端
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.92.135:2181", retryPolicy);
            client.start();

            //建立分布式锁, 锁空间的根节点路径为/curator/lock
            InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
            mutex.acquire();
            //得到了锁, 进行业务流程
            num++;
            System.out.println("当前线程ID是:"+Thread.currentThread().getId()+",数字是:"+num);
            //完成业务流程, 释放锁
            mutex.release();

            //关闭客户端
            client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



}

 

测试代码以下:

public  static  void main(String args[]){
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++){
            executorService.execute(new MyClient());
        }
        executorService.shutdown();
    }

 

源码连接

相关文章
相关标签/搜索