Zookeeper分佈式鎖

分佈式鎖解決思路

  分佈式鎖使用zk,在zk上建立一個臨時節點(有效期)分佈式

  使用臨時節點做爲鎖,由於節點不容許重複。ide

  若是能建立節點成功,生成訂單號,若是建立節點失敗,等待。spa

  臨時節點zk關閉,釋放鎖,其餘節點就能夠從新生成訂單號。code

小案例

  依賴orm

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

 

  OrderNumber生成訂單blog

 

public class OrderNumber {
    private static Integer number=0; //生成訂單號 public String getNumber(){ SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); ++number; return sdf.format(new Date())+"\t"+number; } }

 

  OrderService打印訂單號遞歸

 

public class OrderService implements Runnable{
    private static OrderNumber orderNumber=new OrderNumber(); private Lock lock=new ZkLockImpl(); //生成訂單 public void getOrderNumber(){ //獲取鎖  lock.getLock(); //生成訂單號 System.out.println("訂單號生成成功:"+orderNumber.getNumber()); //釋放鎖  lock.unLock(); } @Override public void run() { getOrderNumber(); } public static void main(String[] args) { for (int i=1;i<=100;i++){ new Thread(new OrderService()).start(); } } }

 

   Lock文接口接口

public interface Lock {
    //獲取鎖
    public void getLock();

    //釋放鎖
    public void unLock();
}

 

  ZookeeperLock實現進程

public abstract class  ZookeeperLock implements Lock{
    /**
     * 鏈接地址
     */
    private static final String ZK_ADDRESS="0.0.0.0:2181";


    protected ZkClient zkClient=new ZkClient(ZK_ADDRESS);
    /**
     * 每個進程在建立節點時,實際上就是得到了一把鎖
     * 若是在獲取鎖是發現返回值爲true,表明當前沒有鎖,我能夠使用
     * 若是返回值爲false,表明鎖正在被佔用,那麼我只能等待
     *
     */
    @Override
    public void getLock() {
        //獲取一把鎖
        if (tryLock()){
            System.out.println("獲取到鎖資源");
        }else{
            //else表明鎖正在被佔用,請等待
            waitLock();
            //遞歸,再次獲取鎖
            getLock();
        }
    }

    @Override
    public void unLock() {
        //非等於空表明建立了訂單號
        if (zkClient!=null){
            //關閉會話,刪除節點
            zkClient.close();
        }
    }



    //獲取鎖資源
    public abstract boolean tryLock();


    //等待
    public abstract void waitLock();
}

 

  ZklockImpl實現資源

public class ZkLockImpl extends ZookeeperLock{
    private CountDownLatch countDownLatch = null;
    @Override
    public boolean tryLock() {
        try {
            //建立臨時節點
            zkClient.createEphemeral("/zkTemp");
            return true;
        }catch (Exception ex){
            return false;
        }

    }

    @Override
    public void waitLock() {
        //監聽節點是否被刪除了
        IZkDataListener iZkDataListener=new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            @Override
            public void handleDataDeleted(String s) throws Exception {
                if(countDownLatch!=null){
                    //釋放掉
                    countDownLatch.countDown();
                }
            }
        };
        //若是已經存在zkTemp節點,就等待
        if(zkClient.exists("/zkTemp")){
            countDownLatch=new CountDownLatch(1);
            System.out.println("訂單號重複,請等待=================================");
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
相關文章
相關標籤/搜索