`
weitao1026
  • 浏览: 1053816 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

如何使用zookeeper来完成非公平锁的模拟

 
阅读更多

如何使用zookeeper来完成非公平锁的模拟,在这之前,我们先来,了解下公平锁和非公平锁的区别。

  JAVA JDK提供了公平锁,与非公平锁,但这种实现是基于同一个JVM来说的,
  如果同一台机器上,不同的JVM,则可以使用文件锁,来实现,但是这些并不是分布式的模式,虽然可以通过RMI的方式来实现,
  但比较繁琐。在分布式的场景里,我们可以轻松的使用zookeeper来实现公平锁与非公平锁
 
基于zookeeper实现的公平锁与非公平锁的区别
 
先来通俗的看下二者的区别

公平锁,即先来者先得,只有一个厕所的卫生间,想进去只能是按排队顺序来的,比较公平,first挂掉或释放后,会由secend得到锁,依次类推。

非公平锁,比较暴力,只有一个厕所的卫生间,不用排队,外面围了一堆人等着上厕所,当里面的人出来时,外面的人谁强势,而且力气大,谁就能进去,
极端情况下,如果两个人一样力气大,这时候就该厕所门发挥作用了,一次只能挤进去一个人,反映到我们的程序中,这时候就需要代码同步了,保证
任何时候,只有一个人可以拿到锁。

二者的相同点,都保证了,任何情况下,都只能一个人得到某种资源。但实现的方式不同。

 

 


实现简述:分布式非公平锁的创建,除了得到锁外,其他的多个监听器,监听同一个锁的情况

实现的流程步骤如下:

序号 介绍 1 创建一个持久znode 2 多个程序并发的去zk服务上,创建同一个短暂无时序性的节点路径,当一个程序,得到锁时,其他程序,只能监听,不能再次创建,创建时需要同步策略 3 同一时刻只能有一个创建成功者,能得到锁 4 没成功者,统一监视得到锁的节点 5 如果中间得到锁的节点,释放了,或者出意外挂掉了,则重复步骤1,2,3,4


拓扑图如下:



代码如下:

Java代码 复制代码 收藏代码
  1. /*** 
  2.  * @author qin dong liang 
  3.  *  
  4.  * */  
  5. public class LockUnFair3  implements Watcher {  
  6.       
  7.       
  8.     /** 
  9.      * ZK实例 
  10.      * */  
  11.     private ZooKeeper zk;  
  12.       
  13.     /**原子计数锁,防止在zk没有连上前,执行CURD操作*/  
  14.     private CountDownLatch down=new CountDownLatch(1);  
  15.       
  16.     public LockUnFair3() {  
  17.         // TODO Auto-generated constructor stub  
  18.     }  
  19.       
  20.       
  21.       
  22.     public LockUnFair3(String host)throws Exception {  
  23.          this.zk=new ZooKeeper(host, 5000   , new Watcher() {  
  24.               
  25.             @Override  
  26.             public void process(WatchedEvent event) {  
  27.                 // TODO Auto-generated method stub  
  28.                 /**链接上zk服务,岂可取消阻塞计数**/  
  29.                 if(event.getState()==KeeperState.SyncConnected){  
  30.                     down.countDown();  
  31.                 }  
  32.                   
  33.             }  
  34.         });  
  35.     }  
  36.     /** 
  37.      * 字符编码 
  38.      *  
  39.      * **/  
  40.      private static final Charset CHARSET=StandardCharsets.UTF_8;  
  41.        
  42.     @Override  
  43.     public void process(WatchedEvent event) {  
  44.         // TODO Auto-generated method stub  
  45.            
  46.         if(event.getType()==Event.EventType.NodeDeleted){  
  47.               
  48.             //如果发现,监听的节点,挂掉了,那么就重新,进行监听   
  49.             try{  
  50.           // System.out.println("注意有锁退出或释放,公平锁开始抢占........");  
  51.                 System.out.println("3我可以去抢占了");  
  52.                 createTemp();  
  53.         //  check();  
  54.             }catch(Exception e){  
  55.                 e.printStackTrace();  
  56.                   
  57.             }  
  58.         }  
  59.     }  
  60.        
  61.      SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  62.   
  63.        
  64.       /** 
  65.        * 关闭zk连接 
  66.        *  
  67.        * **/  
  68.      public void close()throws Exception{  
  69.          zk.close();  
  70.      }  
  71.         
  72.      Random random=new Random();  
  73.      /*** 
  74.       * 创建锁node,注意是抢占 的 
  75.       *  
  76.       *  
  77.       * */  
  78.      public void createTemp()throws Exception{  
  79.        
  80.           
  81.          Thread.sleep(random.nextInt(2500));//加个线程休眠,实现模拟同步功能  
  82.            
  83.        if(zk.exists("/a/b"this) != null){  
  84.            System.out.println("锁被占用,监听进行中......");  
  85.        }else{  
  86.              
  87.              
  88.              
  89.           String data=zk.create("/a/b""a".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);  
  90.           System.out.println("Lock3创建锁成功,节点路径:    "+data);  
  91.             
  92.        }  
  93.            
  94.         // System.out.println("2"+data);  
  95.            
  96.      }  
  97.        
  98.     public static void main(String[] args)throws Exception {  
  99.               
  100.             //Slave s=new Slave("192.168.120.128:2181");  
  101.             LockUnFair3 lock=new LockUnFair3("192.168.120.128:2181");  
  102.             //  lock.createPersist();//创建主节点  
  103.              lock.createTemp();  
  104.             // lock.check();  
  105.               Thread.sleep(Long.MAX_VALUE);  
  106.              lock.close();  
  107.               
  108.     }  
  109.        
  110.        
  111.        
  112. }  
/***
 * @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节点维持一个有序的分布式队列,每次只能第一个得到锁,其他的继续等待,下一次的抢占,如此一来,就能保证任何时刻只有一个节点得到锁。

分享到:
评论

相关推荐

    使用zookeeper实现分布式共享锁

    在分布式系统中,由于网络延迟、服务器故障等...总结来说,Zookeeper的分布式共享锁利用了其临时节点和顺序节点的特性,实现了高可用和公平的锁机制。通过合理的设计和优化,可以在分布式环境中有效地协调和管理资源。

    使用ZooKeeper实现分布式锁

    这里,我们将深入探讨如何利用ZooKeeper这一强大的分布式协调服务来实现分布式锁,以解决订单编号的唯一性问题。 ZooKeeper是由Apache Hadoop项目孵化的开源项目,它提供了一个高可用、高性能的分布式协调服务。其...

    基于zookeeper实现的分布式读写锁

    3. **锁的释放**:无论是读锁还是写锁,当客户端完成操作后,都需要释放锁,这通过删除对应的临时节点来实现。Zookeeper的 watches 机制能确保节点的删除会被所有等待的客户端感知,从而触发重新竞争锁的过程。 **...

    zookeeper做分布式锁

    在实际项目中,可以使用Java的ZooKeeper客户端库(如Curator)来简化分布式锁的实现。这些库提供了高级API,帮助开发者更方便地处理ZooKeeper的操作,例如创建、删除节点,以及设置节点监视器等。 总之,ZooKeeper...

    基于zookeeper的分布式锁简单实现

    - **测试代码**:展示了如何在实际应用中使用Zookeeper实现分布式锁的示例,包括创建锁、获取锁、释放锁以及异常处理等操作。 - **实用工具类**:封装了与Zookeeper交互的常用方法,如创建节点、设置监听、检查节点...

    zookeeper的分布式全局锁纯代码解决方案

    它的数据模型——ZNode(节点),可以模拟锁的概念,通过创建、删除和更新ZNode来实现锁的获取和释放。 实现分布式全局锁的基本步骤如下: 1. **创建锁节点**:客户端在Zookeeper上创建临时顺序节点,表示请求锁。...

    Java-zookeeper实践代码(分布式锁/注册中心)

    Zookeeper的节点(ZNode)可以代表锁资源,通过创建临时节点(ephemeral nodes)来表示获取锁。当一个客户端创建了一个临时节点,它就获得了锁。如果该客户端由于网络故障或进程崩溃而消失,Zookeeper会自动删除这个...

    基于zookeeper的分布式锁实现demo

    6. **锁的释放:** 通常在客户端使用完共享资源后,需要删除之前创建的临时节点来释放锁,这是通过删除Zookeeper上的对应节点实现的。 综上所述,`LockUtil`类通过封装了Zookeeper的连接、节点操作、监听机制以及重...

    基于zookeeper实现分布式锁

    zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是集群的管理者。提供了文件系统和通知机制。...在开发项目的过程中,很多大型项目都是分布式部署的,那么我们现在使用zookeeper实现一个分布式锁。

    zookeeper分布式锁实现和客户端简单实现

    在实际应用中,开发人员通常会使用如Java的`org.apache.zookeeper`包或者Python的` kazoo`等客户端库来与Zookeeper交互。这些库提供了丰富的API,使得开发者能够方便地实现包括分布式锁在内的各种功能。 总结,...

    zookeeper 使用 Curator 示例监听、分布式锁

    综上所述,这个示例项目将展示如何使用 Curator 对 ZooKeeper 进行数据操作,以及如何实现基于 ZooKeeper 的分布式锁,这对于构建分布式系统中的并发控制和协调至关重要。通过学习这个示例,你可以深入理解 ...

    Zookeeper双机房容灾方案.pdf

    Zookeeper双机房容灾方案是指在分布式系统中使用Zookeeper来实现高可用性和容灾的方案。本方案使用5个Zookeeper实例来实现高可用性和容灾。 Zookeeper选举机制是指Zookeeper集群中leader的选举机制。Zookeeper...

    C#基于zookeeper分布式锁的实现源码

    在C#开发环境中,我们可以借助外部协调服务,如Apache ZooKeeper,来实现分布式锁。ZooKeeper是一个高可用的分布式协调服务,它提供了诸如命名服务、配置管理、分布式同步、组服务等功能。本篇将深入探讨如何在C#中...

    zookeeper常见面试题

    * ZooKeeper 实现分布式锁可以提供更高的可用性和可靠性,例如,在分布式系统中,可以使用 ZooKeeper 来实现分布式锁,并且可以提供高可用性和可靠性。 * Redis 实现分布式锁可以提供更高的性能和更低的延迟,例如,...

    ZooKeeper典型使用场景

    ### ZooKeeper典型使用场景详解 #### 一、概述 ZooKeeper是一款开源的分布式协调服务框架,主要用于解决分布式系统中的数据一致性问题。它基于Paxos算法实现,确保了即使在网络分区的情况下,也能保证分布式环境下...

    ZooKeeper的简单使用

    总的来说,理解和掌握ZooKeeper的使用对于构建和维护大规模分布式系统至关重要。通过阅读提供的博客文章和分析`Demo1.java`和`Demo2.java`的代码,我们可以深入学习ZooKeeper的API用法和实际应用场景,提升在分布式...

    apache zookeeper使用方法实例详解

    ZooKeeper 的主要特点是提供了一个简洁的接口,开发人员可以使用 ZooKeeper 提供的现成服务来实现分布式系统的配置管理、组管理、Leader 选举等功能。 ZooKeeper 的使用方法实例详解可以分为四个基本要求:(1)...

    zookeeper分布式锁实例源码

    在实践中,ZooKeeper的分布式锁解决方案需要考虑的方面还包括异常处理(如网络分区)、锁的超时机制、公平性策略(确保等待时间最长的线程优先获得锁)以及锁的粒度(细粒度锁可减少锁竞争,但会增加系统复杂性)。...

    使用spring boot + dubbo + zookeeper搭建完成案例

    6. **创建服务消费者**:在服务消费者模块中,使用`@Reference`注解来引入需要消费的服务,然后就可以在业务代码中调用服务了。 7. **启动Zookeeper**:启动Zookeeper,服务提供者会将自己的元数据注册到Zookeeper...

    Zookeeper 分布式重入排它锁实现

    2. **顺序节点**:在创建临时节点时,Zookeeper会自动为每个节点添加一个唯一的序列号,这样可以确保节点的创建顺序,为锁的公平性提供基础。 3. **监听机制**:客户端可以通过监听父节点的变化,来得知是否有其他...

Global site tag (gtag.js) - Google Analytics