zookeeper分布式锁与Redis分布式锁比较

zookeeper分布式锁与Redis分布式锁比较

1.zookeeper实现分布式锁方案

a.争抢锁,只有一个人能获得锁

b.获得锁,客户端出现问题,临时节点(session)

c.锁被释放,删除,如何通知其他客户端

c-1: 主动轮询,心跳:弊端:延迟,压力

c-2: watch: 解决延迟问题。 弊端:压力

c-3: sequence+watch:watch 前一个,最小的获得锁,一旦最小的释放了锁,成本:zk只需要给第二个发时间回调

2.Redis实现分布式锁方案

a.使用setnx()方法,获取锁信息

b.设置过期时间,防止客户端down机,造成死锁

c.多线程(守护线程),监控锁,业务还未处理完,锁过期,自动延期

3.对比zookeeper与redis分布式锁的实现方案

3.1 从获得锁的速度上,redis的速度优于zookeeper

3.2从方案实现的角度,zookeeper实现相对redis简单,zookeeper只管获取锁和回调,redis还要增加线程对锁进行监控。

4.Zookeeper分布式锁的具体实现

public class ZKUtils {
  private  static ZooKeeper zk;

  private static String address = "192.168.7.230:2181,192.168.7.240:2180,192.168.7.71:2181/testDistributeLock";

  private static DefaultWatch watch = new DefaultWatch();

  private static CountDownLatch init  =  new CountDownLatch(1);
  public static ZooKeeper  getZK(){

    try {
        zk = new ZooKeeper(address,1000,watch);
        watch.setCc(init);
        init.await();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return zk;
 }
}
public class WatchCallBack   implements Watcher, AsyncCallback.StringCallback ,AsyncCallback.Children2Callback ,AsyncCallback.StatCallback {
    ZooKeeper zk ;
    String threadName;
    CountDownLatch cc = new CountDownLatch(1);
   String pathName;

public String getPathName() {
    return pathName;
}

public void setPathName(String pathName) {
    this.pathName = pathName;
}

public String getThreadName() {
    return threadName;
}

public void setThreadName(String threadName) {
    this.threadName = threadName;
}

public ZooKeeper getZk() {
    return zk;
}

public void setZk(ZooKeeper zk) {
    this.zk = zk;
}

public void tryLock(){
    try {

        System.out.println(threadName + "  create....");
        //            if(zk.getData("/"))
            zk.create("/lock",threadName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,this,"abc");
                    cc.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void unLock(){
    try {
        zk.delete(pathName,-1);
        System.out.println(threadName + " over work....");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (KeeperException e) {
        e.printStackTrace();
    }
}
                                                                                         @Override                                                 
public void process(WatchedEvent event) {
        //如果第一个哥们,那个锁释放了,其实只有第二个收到了回调事件!!
    //如果,不是第一个哥们,某一个,挂了,也能造成他后边的收到这个通知,从而让他后边那个跟去watch挂掉这个哥们前边的。。。
    switch (event.getType()) {
        case None:
            break;
        case NodeCreated:
            break;
        case NodeDeleted:
            zk.getChildren("/",false,this ,"sdf");
            break;
        case NodeDataChanged:
            break;
        case NodeChildrenChanged:
            break;
    }

}

@Override
public void processResult(int rc, String path, Object ctx, String name) {
    if(name != null ){
        System.out.println(threadName  +"  create node : " +  name );
        pathName =  name ;
        zk.getChildren("/",false,this ,"sdf");
    }

}

//getChildren  call back
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {

    //一定能看到自己前边的。。
    //        System.out.println(threadName+"look locks.....");
//        for (String child : children) {
//            System.out.println(child);
//        }
Collections.sort(children);
    int i = children.indexOf(pathName.substring(1));
        //是不是第一个
    if(i == 0){
        //yes
        System.out.println(threadName +" i am first....");
        try {
            zk.setData("/",threadName.getBytes(),-1);
            cc.countDown();

        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }else{
        //no
        zk.exists("/"+children.get(i-1),this,this,"sdf");
    }

}

  @Override
  public void processResult(int rc, String path, Object ctx, Stat stat) {
    //偷懒
  }
}    
public class TestDistributeLock {
  ZooKeeper zk ;

  @Before
  public void conn (){
      zk  = ZKUtils.getZK();
  }

@After
public void close (){
    try {
        zk.close();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Test
public void lock(){

    for (int i = 0; i < 10; i++) {
        new Thread(){
            @Override
            public void run() {
                WatchCallBack watchCallBack = new WatchCallBack();
                watchCallBack.setZk(zk);
                String threadName = Thread.currentThread().getName();
                watchCallBack.setThreadName(threadName);
                //每一个线程:
                //抢锁
                watchCallBack.tryLock();
                //干活
                System.out.println(threadName+" working...");
                //                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                    //释放锁
                    watchCallBack.unLock();
                            }
        }.start();
    }
    while(true){

    }
  }
}

你可能感兴趣的:(分布式,redis,分布式,zookeeper)