Zookeeper 분산 잠금 구현

1. 전통적인 업무 장면은 하나의 프로젝트에서 전체 국면의 유일한 ID를 생성해야 한다. 현재의 방안은 UUID, 타임 스탬프가 있다.다중 스레드 시뮬레이션으로 생성합니다.
무엇이 분포식 자물쇠입니까?분포식 자물쇠는 분포식 시스템이나 서로 다른 시스템 간에 공유 자원에 공동으로 접근하는 것을 제어하는 자물쇠의 일종이다. 만약에 서로 다른 시스템이나 같은 시스템의 서로 다른 호스트 간에 특정한 자원을 공유할 때 서로의 간섭을 방지하고 일치성을 확보해야 한다.
분포식 시스템 상황에 문제가 발생할 수 있습니다. 집단이 있기 때문에 많은 서버가 있습니다. 모든 서버는 자신의 웹 용기를 가지고 같은 시간에 생성된 전역의 유일한 id가 나타나는 현상을 초래할 수 있습니다.위의 문제에 대응하기 위해 현재 아래의 몇 가지 해결 방안: 1.레디스를 사용하여 미리 생성한 다음 레디스에서 찾으세요. 2.Zookeeper의 임시 노드에 분산 잠금을 사용합니다.분포식 자물쇠를 사용하는 것이 다른 실현 방식에 비해 장단점: 1.데이터베이스를 이용하여 분포식 자물쇠를 실현하는 것은 데이터베이스에 데이터를 추가하고 버전 번호 등 기술을 이용하는 것이다.이런 실현 방식의 성능이 너무 나빠서 라인에 이상이 발생할 때 자물쇠가 사라지는 현상이 발생하기 쉽다.2.redis를 사용하여 자물쇠의 실효 시간을 제어하기 어렵고 자물쇠가 사라지기 쉬우며 막히지 않고 다시 들어갈 수 없습니다.Zookeeper를 사용하여 분포식 자물쇠를 실현하는 것은 상대적으로 간단하고 신뢰성이 강하며 임시 노드를 사용하면 실효 시간을 제어하기 쉽다(zk 닫기)
****Zookeeper****를 사용하여 분포식 자물쇠를 실현하기: 원리:zookeeper를 사용하여 임시 시퀀스 노드를 생성하여 분포식 자물쇠를 생성하고 순서대로 실행하는 프로그램에 적용된다. 대체적인 사고방식은 임시 시퀀스 노드를 생성하여 최소 시퀀스 노드를 찾아내고 분포식 자물쇠를 가져오는 것이다. 프로그램이 실행된 후에 이 시퀀스 노드는 사라지고watch를 통해 노드의 변화를 감시하고 나머지 노드에서 최소 시퀀스 노드를 찾아 분포식 자물쇠를 얻는다.상응하는 처리를 집행하고 순서대로 유추하다.
Zookeeper를 이용하여 분포식 자물쇠를 실현하는 원리 해석: 자물쇠를 다시 입력할 수 있는 메커니즘을 사용하는 것과 같이 ID를 생성하기 전에 자물쇠를 가져옵니다. 만약에 이 자물쇠가 다른 사람이 사용하고 있다면 기다린 다음에 다시 가져옵니다. 생성이 끝난 후에 자물쇠를 풀어줍니다. (클라이언트를 닫습니다) 대응하는 원리는 임시 노드/lock을 만드는 것입니다.이 노드가 존재하면 기다린다. (Zookeeper의 특성, 노드 이름의 유일성 때문에) 잠금을 기다릴 때 Zookeeper의 이벤트 감청을 이용한다. 이 블로그에 상세한 소개가 있다.https://mp.csdn.net/mdeditor/88979697#
구현 코드는 다음과 같습니다.
package com.cqr.demo.com.cqr.demo.test;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ProjectName: car-zook
 * @Package: com.cqr.demo.com.cqr.demo.test
 * @ClassName: OrderNumGenerator
 * @Author: XW
 * @Description: ${description}
 * @Date: 2019/4/9 14:39
 * @Version: 1.0
 */
public class OrderNumGenerator {
    public static int count = 0;

    public String getNumber() {
        try {
            Thread.sleep(200);
        } catch (Exception e) {
        }
        SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return simpt.format(new Date()) + "-" + ++count;
    }
}
// 
package com.cqr.demo.com.cqr.demo.test;

/**
 * @ProjectName: car-zook
 * @Package: com.cqr.demo.com.cqr.demo.test
 * @ClassName: Lock
 * @Author: XW
 * @Description: ${description}
 * @Date: 2019/4/9 13:53
 * @Version: 1.0
 */
public interface Lock {

    // 
    void getLock();

    // 
    void unlock();


}

Lock 인터페이스를 위한 추상 클래스 만들기
package com.cqr.demo.com.cqr.demo.test;

import org.I0Itec.zkclient.ZkClient;

/**
 * @ProjectName: car-zook
 * @Package: com.cqr.demo.com.cqr.demo.test
 * @ClassName: ZookeeperAbstractLock
 * @Author: XW
 * @Description: ${description}
 * @Date: 2019/4/9 20:54
 * @Version: 1.0
 */
public  abstract class ZookeeperAbstractLock implements Lock{

    // zookeeper 
    private static final String CONNECTSTRING = "127.0.0.1:2181";
    //  zookeeper 
    protected ZkClient zkClient = new ZkClient(CONNECTSTRING);
    protected static final String PATH = "/lock";


    @Override
    public void getLock() {
        if(trylock()){
            System.out.println(" ");
        }else{
            // , , 
            waitLock();
            // , 
            getLock();
        }
    }

    protected abstract void waitLock();

    protected abstract boolean trylock();

    @Override
    public void unlock() {
        if(zkClient!=null){
            // zookeeper 
            zkClient.close();
        }
    }
}

package com.cqr.demo.com.cqr.demo.test;

import org.I0Itec.zkclient.IZkDataListener;

import java.util.concurrent.CountDownLatch;

/**
 * @ProjectName: car-zook
 * @Package: com.cqr.demo.com.cqr.demo.test
 * @ClassName: ZookeeperDistrbuteLock
 * @Author: XW
 * @Description: ${description}
 * @Date: 2019/4/9 21:00
 * @Version: 1.0
 */
public class ZookeeperDistrbuteLock extends  ZookeeperAbstractLock{
    // , 
    private CountDownLatch countDownLatch=null;
    @Override
    protected 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();
                }
            }
        };
        // 
        zkClient.subscribeDataChanges(PATH,iZkDataListener);
        if(zkClient.exists(PATH)){
            // 
            countDownLatch=new CountDownLatch(1);
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        //  
        zkClient.unsubscribeDataChanges(PATH, iZkDataListener);
    }

    @Override
    protected boolean trylock() {
        try {
            zkClient.createEphemeral(PATH);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}
package com.cqr.demo.com.cqr.demo.test;

/**
 * @ProjectName: car-zook
 * @Package: com.cqr.demo.com.cqr.demo.test
 * @ClassName: OrderService
 * @Author: XW
 * @Description: ${description}
 * @Date: 2019/4/9 14:41
 * @Version: 1.0
 */
public class OrderService implements Runnable {
    private OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
    private Lock lock = new ZookeeperDistrbuteLock();

    public void run() {
        getNumber();
    }

    public void getNumber() {
        try {
            lock.getLock();
            String number = orderNumGenerator.getNumber();
            System.out.println(Thread.currentThread().getName() + ", ID:" + number);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread( new OrderService()).start();
        }

    }
}

좋은 웹페이지 즐겨찾기