Zookeeper实战分布锁
一,分布式锁实现的技术
基于数据实现分布式锁
性能较差,容易出现单点故障
锁没有失效事件,容易死锁。
非阻塞式
不可重入
基于缓存实现分布式锁
锁没有失效事件,容易死锁
非阻塞式
不可重入
基于Zookeeper实现分布式锁
实现相对简单
可靠性高
性能较好
二,Zookeeper应用场景
数据发布订阅
负载均衡
命名服务
分布式协调
集群管理
配置管理
分布式队列
分布式锁
三,Zookeeper实战分布式锁



/**
* 获取锁和释放锁真正实现的类
*/
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();
}
}
}
}
public abstract class ZookeeperLock implements Lock{
/**
* 创建zkClient连接对象
*/
private static final String ZK_ADDRESS="0.0.0.0:2181";
protected ZkClient zkClient=new ZkClient(ZK_ADDRESS);
/**
* 每一个进程在创建节点时,实际上就是获得了一把锁,如果在获取锁是发现返回值为true,代表当前没有锁,我可以使用,如果返回值为false,代表锁正在被占用,那么我只能等待
* @return
*/
@Override
public void getLock() {
//获取一把锁
if(tryLock()){
System.out.println("获取到锁资源");
}else{
//当返回值为false时,代表当前锁正在被使用,等待
waitLock();
//等待之后我得再次获取,我不再次获取我怎么能得到锁资源
getLock();
}
}
/**
* 释放锁,zk关闭
*/
@Override
public void unLock() {
if(zkClient!=null){
zkClient.close();
}
}
//获取锁资源
public abstract boolean tryLock();
//等待
public abstract void waitLock();
}
三,分布式锁解决思路
分布式锁使用zk,在zk上创建一个临时节点(有效期) ,使用临时节点作为锁,因为节点不允许重复。
如果能创建节点成功,生成订单号,如果创建节点失败,等待。临时节点zk关闭,释放锁,其他节点就可以重新生成订单号。
浙公网安备 33010602011771号