上篇文章,散仙介绍了,分布式环境下,基于zookeeper实现的公平的锁,这篇,我们来看下,如何使用zookeeper来完成非公平锁的模拟,在这之前,我们先来,了解下公平锁和非公平锁的区别。
JAVA JDK提供了公平锁,与非公平锁,但这种实现是基于同一个JVM来说的,
如果同一台机器上,不同的JVM,则可以使用文件锁,来实现,但是这些并不是分布式的模式,虽然可以通过RMI的方式来实现,
但比较繁琐。在分布式的场景里,我们可以轻松的使用zookeeper来实现公平锁与非公平锁
基于zookeeper实现的公平锁与非公平锁的区别
先来通俗的看下二者的区别
公平锁,即先来者先得,只有一个厕所的卫生间,想进去只能是按排队顺序来的,比较公平,first挂掉或释放后,会由secend得到锁,依次类推。
非公平锁,比较暴力,只有一个厕所的卫生间,不用排队,外面围了一堆人等着上厕所,当里面的人出来时,外面的人谁强势,而且力气大,谁就能进去,
极端情况下,如果两个人一样力气大,这时候就该厕所门发挥作用了,一次只能挤进去一个人,反映到我们的程序中,这时候就需要代码同步了,保证
任何时候,只有一个人可以拿到锁。
二者的相同点,都保证了,任何情况下,都只能一个人得到某种资源。但实现的方式不同。
实现简述:分布式非公平锁的创建,除了得到锁外,其他的多个监听器,监听同一个锁的情况
实现的流程步骤如下:
序号 | 介绍 |
1 | 创建一个持久znode |
2 | 多个程序并发的去zk服务上,创建同一个短暂无时序性的节点路径,当一个程序,得到锁时,其他程序,只能监听,不能再次创建,创建时需要同步策略 |
3 | 同一时刻只能有一个创建成功者,能得到锁 |
4 | 没成功者,统一监视得到锁的节点 |
5 | 如果中间得到锁的节点,释放了,或者出意外挂掉了,则重复步骤1,2,3,4 |
拓扑图如下:
代码如下:
/***
* @author qin dong liang
*
* */
public class LockUnFair3 implements Watcher {
/**
* ZK实例
* */
private ZooKeeper zk;
/**原子计数锁,防止在zk没有连上前,执行CURD操作*/
private CountDownLatch down=new CountDownLatch(1);
public LockUnFair3() {
// TODO Auto-generated constructor stub
}
public LockUnFair3(String host)throws Exception {
this.zk=new ZooKeeper(host, 5000 , new Watcher() {
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
/**链接上zk服务,岂可取消阻塞计数**/
if(event.getState()==KeeperState.SyncConnected){
down.countDown();
}
}
});
}
/**
* 字符编码
*
* **/
private static final Charset CHARSET=StandardCharsets.UTF_8;
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
if(event.getType()==Event.EventType.NodeDeleted){
//如果发现,监听的节点,挂掉了,那么就重新,进行监听
try{
// System.out.println("注意有锁退出或释放,公平锁开始抢占........");
System.out.println("3我可以去抢占了");
createTemp();
// check();
}catch(Exception e){
e.printStackTrace();
}
}
}
SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 关闭zk连接
*
* **/
public void close()throws Exception{
zk.close();
}
Random random=new Random();
/***
* 创建锁node,注意是抢占 的
*
*
* */
public void createTemp()throws Exception{
Thread.sleep(random.nextInt(2500));//加个线程休眠,实现模拟同步功能
if(zk.exists("/a/b", this) != null){
System.out.println("锁被占用,监听进行中......");
}else{
String data=zk.create("/a/b", "a".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("Lock3创建锁成功,节点路径: "+data);
}
// System.out.println("2"+data);
}
public static void main(String[] args)throws Exception {
//Slave s=new Slave("192.168.120.128:2181");
LockUnFair3 lock=new LockUnFair3("192.168.120.128:2181");
// lock.createPersist();//创建主节点
lock.createTemp();
// lock.check();
Thread.sleep(Long.MAX_VALUE);
lock.close();
}
}
以上是实现的代码,需要注意的是,在最后抢占锁时,可能会一下多个节点同时去建立名字一样的节点,由于zookeeper的特点,只能由一个建立成功,其他的会抛出异常,为了避免这种情况,散仙,目前的想到的是,在创建一个节点时,通过线程随机休眠,来达到一个同步情况,但这扔有极端情况,虽然几率很小,就是分布式环境下可能有多个节点随机休眠的时间是一样的,所以第二种做法,可以在zk节点维持一个有序的分布式队列,每次只能第一个得到锁,其他的继续等待,下一次的抢占,如此一来,就能保证任何时刻只有一个节点得到锁。
如有什么不足之处,欢迎指正! ^_^
- 大小: 56.8 KB
分享到:
相关推荐
分布式之Zookeeper(高清视频教程).rar
ubuntu系统部署完全分布式hadoop时,先部署了zookeeper和hbase
分布式框架Zookeeper之服务注册与订阅.........................
分布式架构Zookeeper入门实战到底层原理剖析
Zookeeper伪分布式集群搭建描述伪分布式集群就是在一台机器部署多个zk应用,部署之前服务器需要有jdk环境 java -version可以显示相关java
互联网大厂必会的高薪技能之分布式架构Zookeeper入门实战到底层原理剖析
server程序入口(启动类在zookeeper-server/src/main/java文件夹中,org.apache.zookeeper.server.quorum.QuorumPeerMain),program argument为conf/zoo.cfg,将conf/log4j.properties配置拷贝到zookeeper-server/...
三台主机搭建分布式Zookeeper,完全分布式搭建zookeeper集群,及其简单的操作
分布式服务框架 Zookeeper -- 管理分布式环境中的数据
本文来自于cnblogs,说到分布式开发Zookeeper是必须了解和掌握的,分布式消息服务kafka、hbase到hadoop等分布式大数据处理都会用到Zookeeper,所以在此将Zookeeper作为基础来讲解。Zookeeper是分布式服务框架,主要...
#资源达人分享计划#
详解Zookeeper伪分布式集群环境搭建过程
基于zookeeper的分布式锁简单实现,包含测试代码,实用工具类
ZooKeeper 是一个开源的分布式 应用程序协调服务器,其为分布式系统提供一致性服务。其一致性是通过基于 Paxos 算法的 ZAB 协议完成的。其主要功能包括:配置维护、域名服务、分布式同步、集群管理等。 zookeeper 的...
#资源达人分享计划#
从Paxos到Zookeeper分布式一致性原理与实践 + ZooKeeper-分布式过程协同技术详解
在分布式高并发的情况下,多个访问之间拥有唯一的一个订单编号,多次提交的订单不会出现重复的,只能是唯一的,ZooKeeper就很好的解决了唯一性
从传统JavaWeb转入分布式系统应用,再到接触分布式协调框架ZooKeeper,通过痛苦的思维逻辑和理念转变,历经一个月时间,小伙伴们终于把ZooKeeper嵌入到了BoCloud博云的BeyondContainer中,并在其上进行相应功能的...
分布式服务框架zookeeper 3.4.13版本,主要用于构建RPC服务与常见集群等。