知识点
相关文章
更多最近更新
更多分布式助手Zookeeper(七) - 三劫散仙
2019-03-14 22:52|来源: 网路
上篇文章,散仙介绍了,分布式环境下,基于zookeeper实现的公平的锁,这篇,我们来看下,如何使用zookeeper来完成非公平锁的模拟,在这之前,我们先来,了解下公平锁和非公平锁的区别。
JAVA JDK提供了公平锁,与非公平锁,但这种实现是基于同一个JVM来说的,
如果同一台机器上,不同的JVM,则可以使用文件锁,来实现,但是这些并不是分布式的模式,虽然可以通过RMI的方式来实现,
但比较繁琐。在分布式的场景里,我们可以轻松的使用zookeeper来实现公平锁与非公平锁
基于zookeeper实现的公平锁与非公平锁的区别
先来通俗的看下二者的区别
公平锁,即先来者先得,只有一个厕所的卫生间,想进去只能是按排队顺序来的,比较公平,first挂掉或释放后,会由secend得到锁,依次类推。
非公平锁,比较暴力,只有一个厕所的卫生间,不用排队,外面围了一堆人等着上厕所,当里面的人出来时,外面的人谁强势,而且力气大,谁就能进去,
极端情况下,如果两个人一样力气大,这时候就该厕所门发挥作用了,一次只能挤进去一个人,反映到我们的程序中,这时候就需要代码同步了,保证
任何时候,只有一个人可以拿到锁。
二者的相同点,都保证了,任何情况下,都只能一个人得到某种资源。但实现的方式不同。
实现简述:分布式非公平锁的创建,除了得到锁外,其他的多个监听器,监听同一个锁的情况
实现的流程步骤如下:
拓扑图如下:
代码如下:
以上是实现的代码,需要注意的是,在最后抢占锁时,可能会一下多个节点同时去建立名字一样的节点,由于zookeeper的特点,只能由一个建立成功,其他的会抛出异常,为了避免这种情况,散仙,目前的想到的是,在创建一个节点时,通过线程随机休眠,来达到一个同步情况,但这扔有极端情况,虽然几率很小,就是分布式环境下可能有多个节点随机休眠的时间是一样的,所以第二种做法,可以在zk节点维持一个有序的分布式队列,每次只能第一个得到锁,其他的继续等待,下一次的抢占,如此一来,就能保证任何时刻只有一个节点得到锁。
如有什么不足之处,欢迎指正! ^_^
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节点维持一个有序的分布式队列,每次只能第一个得到锁,其他的继续等待,下一次的抢占,如此一来,就能保证任何时刻只有一个节点得到锁。
如有什么不足之处,欢迎指正! ^_^
转自:http://qindongliang.iteye.com/blog/2028241
相关问答
更多-
分布式锁用zookeeper还是redis好[2023-10-04]
1. 不能重入 2. 没有本地锁,并发性能会比较差,不使用用在并发争锁较多的场景下。本地锁非自旋 3. 未考虑锁等待排序. 这个是redis很难实现的. 可以通过redis的list实现,但缺点是list下每个子节点无超时时间. redis也无法进行模糊查询 key*. 故还是通过zookeeper实现比较好. 但zookeeper 会遇到性能瓶颈,我们线下的就出现了,经常注册不上的情况. zookeeper原理是临时节点 -
mysql如何做成分布式?[2023-11-14]
Mysql本身支持”复制“功能,可以将整个数据库的全部或部分实时同步到另外的服务器上。应用程序通过智能算法,可以同时使用这些数据库,如果其中一个故障,可以做到应用程序继续运行。 这里面的技术也挺多,你搜一下”Mysql 复制“,”mysql 双MASTER",有很多资料的。 ----------------------------------- 呵呵,放松,一切都会好起来的! -
zookeeper怎么实现分布式锁[2022-06-01]
1. 利用节点名称的唯一性来实现共享锁 ZooKeeper抽象出来的节点结构是一个和unix文件系统类似的小型的树状的目录结构。ZooKeeper机制规定:同一个目录下只能有一个唯一的文件名。例如:我们在Zookeeper目录/test目录下创建,两个客户端创建一个名为Lock节点,只有一个能够成功。 算法思路: 利用名称唯一性,加锁操作时,只需要所有客户端一起创建/test/Lock节点,只有一个创建成功,成功者获得锁。解锁时,只需删除/test/Lock节点,其余客户端再次进入竞争创建节点,直到所有客户 ... -
分布式锁用zookeeper还是redis好[2022-12-29]
1. 不能重入 2. 没有本地锁,并发性能会比较差,不使用用在并发争锁较多的场景下。本地锁非自旋 3. 未考虑锁等待排序. 这个是redis很难实现的. 可以通过redis的list实现,但缺点是list下每个子节点无超时时间. redis也无法进行模糊查询 key*. 故还是通过zookeeper实现比较好. 但zookeeper 会遇到性能瓶颈,我们线下的就出现了,经常注册不上的情况. zookeeper原理是临时节点 -
分布式独占锁机制[2022-06-17]
当需要获取共享锁是,所有客户端到/shared_lock节点下面创建一个临时顺序节点,/shared_lock/[hostname]-请求类型(W | R)-序号,该节点代编了一个共享锁。 如果是读请求,则创建/shared_lock/192.168.0.1-R-000000000001; 如果是写请求,则创建/shared_lock/192.168.0.1-W-000000000001; -
分布式架构现在很火吗?zookeeper dubbo可以[2022-03-15]
分布式架构是架构设计的基础,也叫集群架构。 主要目的是为了避免服务的单节点和将请求均衡分布给多台机器。 -
什么是分布式系统?[2022-11-11]
一、DFS为何物? DFS 即微软分布式文件系统的简称,系统管理员可以利用它来有效的整合网络资源,并把这些资源以单一的层次结构呈现给网络用户。管理员利用它可以把资源发布成一 个树形结构,这样大大简化了为用户进行资源配置和对资源管理的工作量。我们可以在不同的机器上调整和移动文件,这不会影响到用户的访问。 二、为什么要使用DES? 1、DFS使用了现有网络中的Share权限,管理员不必进行新的配置 2、通过一个DFS树形结构用户就可以访问多个网络资源,而不用再把远程驱动器映射到本地共享资源中。 3、DFS可以配 ... -
什么是分布式系统?[2024-03-23]
分布式系统(distributed system)是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。内聚性是指每一个数据库分布节点高度自治,有本地的数据库管理系统。透明性是指每一个数据库分布节点对用户的应用来说都是透明的,看不出是本地还是远程。在分布式数据库系统中,用户感觉不到数据是分布的,即用户不须知道关系是否分割、有无复本、数据存于哪个站点以及事务在哪个站点上执行等。 故名思义,分布式 ... -
三层架构与分布式开发有何区别???[2022-04-01]
简单的问题复杂化。简单说三层架构只是一种标准。用什么模式开发都是根据当时项目的需求,包括外部环境。业务逻辑上来的。不一定非要用三层或者分布式。要是贯彻三层的概念我现在的项目就用到了9层。另外分布式是为了处理某些方面的压力,使压力分散开。也不是必要的。还是看情况。 -
什么是分布式缓存?(What is a distributed cache?)[2023-03-16]
是的,服务器a上的一半数据,服务器b上的一半是分布式缓存。 有许多分发数据的方法,尽管某些键的散列似乎是最受欢迎的。 术语服务器和节点通常是可互换的。 节点通常是某些集合的单个单元,通常称为集群。 服务器通常是单个硬件。 在erlang中,您可以在单个服务器上运行erlang运行时的多个实例,因此您将拥有多个erlang节点,但通常您希望每个服务器有一个节点以获得更优化的调度。 (对于非分布式语言和平台,您必须根据需要管理流程。) 如果服务器关闭,并且它是缓存服务器,则数据必须来自其原始源。 EG:缓存通常 ...