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();
    }

 

源碼連接

相關文章
相關標籤/搜索