1、实现原理
分布式系统中分布式锁是经常是经常用到的,比如买票程序,当一个进程在使用公共资源时,其他进程应该处于等待状态,直到当前资源释放后才能获取锁。
zookeeper实现分布式锁的原理如下:
1、创建当前结点
2、获取当前节点的所有兄弟节点
3、判断当节点是否为兄弟节点的第一个第一个节点
3.1、是,获取锁
3.2、不是,获取当前结点的前一个节点,等到前一个节点释放锁后,获取锁
2、java代码实现
package com.cn.willy;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class MyLock {
private static final String URL="192.168.43.134:2181";
private static final int TIME_OUT=5000;
private CountDownLatch latch = new CountDownLatch(1);
private ZooKeeper zooKeeper = null;
private String localPath = "";
private boolean setLocalPath = true;
/**
* 使用构造方法实例化zk实例
*/
public MyLock(){
try{
zooKeeper = new ZooKeeper(URL, TIME_OUT, new Watcher() {
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.None){
if (event.getState() == Event.KeeperState.SyncConnected){
latch.countDown();
System.out.println("connection zookeeper");
}
}
}
});
latch.await();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 递归创建单节点
* @param path
* @return
*/
public String createNode(String path){
String tempPath = "";
try{
if (setLocalPath){
localPath = path;
setLocalPath = false;
}
Stat stat = zooKeeper.exists(path,false);
if(stat == null){
if(path.split("/").length > 2){
createNode(path.substring(0,path.lastIndexOf("/")));
}
if (localPath.equals(path)){
tempPath = zooKeeper.create(path,new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
localPath = tempPath;
}else{
tempPath = zooKeeper.create(path,new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
}catch (Exception e){
e.printStackTrace();
}
return tempPath;
}
/**
* 节点变更监听
*/
Watcher watcher = new Watcher() {
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeDeleted){
//唤醒阻塞节点
synchronized (this){
this.notifyAll();
}
}
}
};
/**
* 获取锁
*/
public void attempLock(){
try{
//1、获取当前结点的所有节点
List<String> list = zooKeeper.getChildren(localPath.substring(0,localPath.lastIndexOf("/")),false);
//2、对几点排序
Collections.sort(list);
//3、判断当前节点是否为第一个节点
int index = list.indexOf(localPath);
//3.1、是第一个节点直接返回
if(index == 0){
return;
}else{
//3.2、不是第一个节点,则获取当前结点的前一个节点
String upPath = list.get(index+1);
Stat stat = zooKeeper.exists(upPath,watcher);
//此时前一个节点已经被处理,表示当前节点可以获取资源
if (stat == null){
attempLock();
}else{
//阻塞当前结点、等待前一个节点完成
synchronized (watcher){
watcher.wait();
}
attempLock();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 释放当前结点
*/
public void releaseLock(){
try{
zooKeeper.delete(localPath,-1);
zooKeeper.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
String path = "/fsm/dep/purch/lock/lock_";
MyLock lock = new MyLock();
System.out.println(lock.createNode(path));
}
}
本文详细介绍了如何使用Zookeeper实现分布式锁,包括其实现原理、Java代码实现过程。通过创建临时顺序节点,利用Zookeeper的特性确保分布式环境中资源的独占访问。
552

被折叠的 条评论
为什么被折叠?



