1. 程式人生 > >最簡單分布式鎖ZK實現方案

最簡單分布式鎖ZK實現方案

zookeeper

分布式鎖簡單封裝

package com.hellojd.cloud.locks.v1;
import org.apache.zookeeper.*;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import static org.apache.zookeeper.Watcher.Event.KeeperState.SyncConnected;

/**
 * 最簡單分布式鎖實現方案
 */
public class ZookerSession implements Watcher {
    private CountDownLatch countDownLatch=new CountDownLatch(1);
    private ZooKeeper zooKeeper;
    private static  class  Singleton{
        private  static  ZookerSession instance;
        static {
            instance = new ZookerSession();
        }

        public static ZookerSession getInstance(){
            return instance;
        }
    }
    public static ZookerSession getInstance(){
        return Singleton.getInstance();
    }


    public ZookerSession() {
        try {
            this.zooKeeper = new ZooKeeper("192.168.0.10:2181",50000,this);
            countDownLatch.await();
            System.out.println("state:  "+zooKeeper.getState());
            System.out.println("connection estalished!!");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public ZooKeeper getZooKeeper(){return this.zooKeeper;}
    @Override
    public void process(WatchedEvent event) {
        if(event.getState()==SyncConnected){
            countDownLatch.countDown();
        }
    }
    public void releaseDistributeLock(Long id){
        String path ="/lock_"+id;
        try {
            zooKeeper.delete(path,-1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }

    public void acquireDistributeLock(Long id){
        String path ="/lock_"+id;
        try {
            zooKeeper.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
//            System.out.println("success to acquire lock "+id);
        } catch (KeeperException e) {
            //沒有獲取到鎖
            int count=0;
            while (true){
                try{
                    Thread.sleep(200);
                    zooKeeper.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                }catch (InterruptedException e1) {
                    count++;
                    continue;
                } catch (KeeperException e1) {
//                    e1.printStackTrace();
                    count++;
                    continue;
                }
//                System.out.println("success to acquire lock "+id);
                break;
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}


2.測試線程

package com.hellojd.cloud.locks.v1;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

/**
 * 測試線程
 */
public class Task implements  Runnable {
    private int loop;
    private Long lockid;
    ZookerSession zs;
    public Task(int loop,Long lockid) {
        zs = ZookerSession.getInstance();
        this.loop = loop;
        this.lockid = lockid;
    }

    @Override
    public void run() {

        ZookerSession.getInstance().acquireDistributeLock(lockid);
        for(int i=0;i<loop;i++){
            int count = getcount();
            System.out.println(Thread.currentThread().getName()+"-->"+count);
            count(++count);
        }
        zs.releaseDistributeLock(lockid);
    }
    //計數
    public void count(int count){
        try {
            Stat s = zs.getZooKeeper().exists("/count", false);
            if(s==null){
                System.out.println("count 不存在");
                zs.getZooKeeper().create("/count",String.valueOf(count).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }else{
                zs.getZooKeeper().setData("/count",String.valueOf(count).getBytes(),-1);
            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public int getcount(){
        try {
            Stat s = zs.getZooKeeper().exists("/count", false);
            if(s==null){
                zs.getZooKeeper().create("/count",String.valueOf(0).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                return 0;
            }else{
                byte[] data = zs.getZooKeeper().getData("/count", false, null);
                return Integer.valueOf(new String(data));
            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return -1;
    }
    public static void main(String[] args) {
        long LOCKID = 2l;
        for(int i=0;i<100;i++){
            new Thread(new Task(1, LOCKID)).start();
        }
    }
}



原理:分布式鎖通過死循環+實現等待效果。如果線程可以創建節點,則成功獲取鎖;

釋放鎖:就是將數據節點在ZK上刪除。


缺點:簡單且性能低。有風險。如果獲取鎖的線程中斷,導致任務異常。



本文出自 “簡單” 博客,請務必保留此出處http://dba10g.blog.51cto.com/764602/1975120

最簡單分布式鎖ZK實現方案