在我们的项目当中,可能有许多组件在并行的运行。这些组件可能需要更新我们的数据存储。所以这些组件应该有解决冲突的能力,避免脏数据。但是这些组件往往运行在不同的服务器上,甚至编程语言,文件系统结构都是不同的。这些差异给我们的分布式协作带来困难。
zookeeper给我们提供了解决方案。那么如何借助zookeeper来管理我们的分布式系统,达到系统之间的协作呢?我们可以通过zookeeper来实现分布式锁的概念,从而达到系统之间的协作目的。
public class DistributedLock { private final ZooKeeper zk; private final String lockBasePath; private final String lockName; private String lockPath; public DistributedLock(ZooKeeper zk, String lockBasePath, String lockName) { this.zk = zk; this.lockBasePath = lockBasePath; this.lockName = lockName; } public void lock() throws IOException { try { // lockPath will be different than (lockBasePath + "/" + lockName) becuase of the sequence number ZooKeeper appends lockPath = zk.create(lockBasePath + "/" + lockName, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); final Object lock = new Object(); synchronized(lock) { while(true) { List<String> nodes = zk.getChildren(lockBasePath, new Watch() { @Override public void process(WatchedEvent event) { synchronized (lock) { lock.notifyAll(); } } }); Collections.sort(nodes); // ZooKeeper node names can be sorted lexographically if (lockPath.endsWith(nodes.get(0)) { return; } else { lock.wait(); } } } } catch (KeeperException e) { throw new IOException (e); } catch (InterruptedException e) { throw new IOException (e); } } public void unlock() throws IOException { try { zk.delete(lockPath, -1); lockPath = null; } catch (KeeperException e) { throw new IOException (e); } catch (InterruptedException e) { throw new IOException (e); } } }
-
构造方法
public DistributedLock(ZooKeeper zk, String lockBasePath, String lockName) { this.zk = zk; this.lockBasePath = lockBasePath; this.lockName = lockName; }
需要给构造方法提供三个参数,zk 表示可以连接到zookeeper服务器的客户端。lockBasePath 准备将节点创建在那个目录路径下。lockName指创建的子目录名称。 -
创建节点
lockPath = zk.create(lockBasePath + "/" + lockName, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
这里注意的地方就是节点的类型是ephemeral并且是sequetial的。也就是说我们可以在lockBasePath下面可以创建多个名为lockName的多个临时节点,这些节点时有序的。sequetial节点的名称可以相同,因为zookeeper将transactionID后缀到节点路径后面以用于区分。这也是实现分布式锁的关键。另外这些节点时临时的,保证当申请锁的程序失去session以后,可以由zookeeper自动去除该节点。 -
申请锁
final Object lock = new Object(); synchronized(lock) { while(true) { List<String> nodes = zk.getChildren(lockBasePath, new Watch() { @Override public void process(WatchedEvent event) { synchronized (lock) { lock.notifyAll(); } } }); Collections.sort(nodes); // ZooKeeper node names can be sorted lexographically if (lockPath.endsWith(nodes.get(0)) { return; } else { lock.wait(); } } }
因为watcher 里面的process()是有外部线程触发的,所以为了保证两次时间上相近的触发操作能够同步执行使用两层的synchronized block。
- 首先从zookeeper lockBasePath目录下面获得所有的名字为lockName的节点。
- 将子节点排序
- 如果该线程创建的节点时最小的节点也就是相对其他节点时最先创建的,那么就获得了锁,跳出while循环执行相应的操作逻辑。否则释放锁,等待节点变化事件触发下一次循环重新申请锁。
- 当执行完操作逻辑以后,就可以释放锁了,也就是删除该线程创建的节点。
相关推荐
在分布式高并发的情况下,多个访问之间拥有唯一的一个订单编号,多次提交的订单不会出现重复的,只能是唯一的,ZooKeeper就很好的解决了唯一性
基于zookeeper的分布式锁简单实现,包含测试代码,实用工具类
Zookeeper实现分布式锁的Demo Zookeeper实现分布式锁的Demo
zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是集群的管理者。提供了文件系统和通知机制。...在开发项目的过程中,很多大型项目都是分布式部署的,那么我们现在使用zookeeper实现一个分布式锁。
基于zookeeper的分布式锁实现demo,可以直接用在生产环境
在程序开发过程中不得不考虑的就是并发问题。在java中对于同一个jvm而言,jdk已经提供了lock和同步等。但是在分布式情况下,往往存在多个进程对一些资源产生竞争...分布式锁顾明思议就是可以满足分布式情况下的并发锁。
吊打面试官之基于zookeeper实现分布式锁源码
基于Zookeeper实现分布式锁实践。Zookeeper是一个分布式的,开源的分布式应用程序协调服务,是Hadoop和hbase的重要组件。zookeeper的数据机构是一种节点树的数据结构,zNode是基本的单位,znode是一种和unix文件系统...
只要创建好一个分布式锁,就要不断轮循这个锁什么时候释放。 zk只会对已经创建分布式锁的系统进行创建监听,所以性能消耗很小 2、运行出现错误 redis创建锁的节点如果挂了,那就只能等待超时才能释放锁 zk因为是创建...
1.zk简介 2.zk实现分布式锁
NULL 博文链接:https://zhouguofeng.iteye.com/blog/2320290
主要介绍了java使用zookeeper实现的分布式锁示例,需要的朋友可以参考下
如何操作Redis和zookeeper实现分布式锁 在分布式场景下,有很多种情况都需要实现最终一致性。在设计远程上下文的领域事件的时候,为了保证最终一致性,在通过领域事件进行通讯的方式中,可以共享存储(领域模型和...
zookeeper客户端。分布式锁。 demo。。
最新版本SpringBoot集成zookeeper实现分布式可重入排他锁实现,支持拓展其他种类锁
此Demo采用zookeeper实现分布式锁,相比于redis实现分布式锁更加可靠
利用springboot集成zookeeper,并利用zookeeper实现分布式锁,避免羊群效应
springboot redis zookeeperlock rabbit实现的分布式锁 代码
zookeeper通过使用curator实现分布式锁来保证数据的一致性。 zookeeper通过使用curator实现分布式锁来保证数据的一致性。