Zookeeper(5)---分布式锁
基于临时序号节点来实现分布式锁
为什么要用临时节点呢?如果拿到锁的服务宕机了,会话失效ZK自己也会删除掉临时的序号节点,这样也不会阻塞其他服务。
流程:
1.在一个持久节点下面创建临时的序号节点作为锁节点,如:/lock/lockId00000001 /lock/lockId00000002
2.获取持久节点下面所有子节点,判断其最小的是不是自己,如果是自己则表示获取锁成功。
3.如果最小的结点不是自己,则阻塞等待,并对lock结点添加监听,如果结点数发生变化了,则说明有释放了锁。但是这里如果存在大量监听,当结点发生变化的时候,可能就会出现羊群效应。因为大家都监听了,同时会通知很多客户端,会造成ZK性能突然下降。
所以这里可以只监听自己前面的那个节点,排队执行,03监听02,02监听01
4.当锁释放,节点监听到变化之后,执行第2步。
释放锁只需要删除对应的临时节点,如果获取到锁的服务宕机了,因为是临时节点也会自己删除的。
代码实现:
- package com.nijunyang.zookeeper.zklock;
- import lombok.Data;
- import org.I0Itec.zkclient.IZkDataListener;
- import org.I0Itec.zkclient.ZkClient;
- import java.util.List;
- import java.util.stream.Collectors;
- /**
- * Description:
- * Created by nijunyang on 2020/11/29 21:51
- */
- public class ZKLock {
- private static final String SERVER = "192.168.0.67:2181";
- private ZkClient zkClient;
- private static final String ROOT_PATH = "/lock";
- public ZKLock() {
- zkClient = new ZkClient(SERVER, 5000, 20000);
- buildRoot();
- }
- private void buildRoot() {
- if (!zkClient.exists(ROOT_PATH)) {
- zkClient.createPersistent(ROOT_PATH);
- }
- }
- /**
- * 加锁
- *
- * @param lockId
- * @param timeout
- * @return
- */
- public Lock lock(String lockId, long timeout) {
- Lock lockNode = createLock(lockId);
- // 尝试激活锁
- tryActiveLock(lockNode);
- if (!lockNode.isActive()) {
- try {
- synchronized (lockNode) {
- lockNode.wait(timeout);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- if (!lockNode.isActive()) {
- throw new RuntimeException("获取锁超时");
- }
- return lockNode;
- }
- /**
- * 释放锁
- *
- * @param lock
- */
- public void unlock(Lock lock) {
- if (lock.isActive()) {
- zkClient.delete(lock.getPath());
- }
- }
- /**
- * 激活锁
- * @param lockNode
- */
- private void tryActiveLock(Lock lockNode) {
- // 判断当前是否为最小节点
- List<String> list = zkClient.getChildren(ROOT_PATH)
- .stream()
- .sorted()
- .map(p -> ROOT_PATH + "/" + p)
- .collect(Collectors.toList());
- String firstNodePath = list.get(0);
- //第一个节点是当前节点,将锁设置为激活
- if (firstNodePath.equals(lockNode.getPath())) {
- lockNode.setActive(true);
- } else {
- //第一个节点不是当前节点,则监听前面一个节点
- String upNodePath = list.get(list.indexOf(lockNode.getPath()) - 1);
- zkClient.subscribeDataChanges(upNodePath, new IZkDataListener() {
- @Override
- public void handleDataChange(String dataPath, Object data) throws Exception {
- }
- @Override
- public void handleDataDeleted(String dataPath) throws Exception {
- //监听之后继续尝试加锁,加锁成功唤醒之前的等待
- tryActiveLock(lockNode);
- synchronized (lockNode) {
- if (lockNode.isActive()) {
- lockNode.notify();
- }
- }
- zkClient.unsubscribeDataChanges(upNodePath, this);
- }
- });
- }
- }
- /**
- * 创建锁节点
- *
- * @param lockId
- * @return Lock
- */
- private Lock createLock(String lockId) {
- String nodePath = zkClient.createEphemeralSequential(ROOT_PATH + "/" + lockId, "write");
- return new Lock(lockId, nodePath);
- }
- @Data
- public static class Lock {
- private String lockId;
- private String path;
- /**
- * 是否激活锁
- */
- private boolean active;
- public Lock(String lockId, String path) {
- this.lockId = lockId;
- this.path = path;
- }
- }
- }
Zookeeper(5)---分布式锁的更多相关文章
- zookeeper实现分布式锁服务
A distributed lock base on zookeeper. zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hiv ...
- [ZooKeeper.net] 3 ZooKeeper的分布式锁
基于ZooKeeper的分布式锁 ZooKeeper 里实现分布式锁的基本逻辑: 1.zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作. 2.想要获取锁的client都在L ...
- 基于 Zookeeper 的分布式锁实现
1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个“类 Unix/Linu ...
- zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- zookeeper 实现分布式锁安全用法
zookeeper 实现分布式锁安全用法 标签: zookeeper sessionExpire connectionLoss 分布式锁 背景 ConnectionLoss 链接丢失 SessionE ...
- 基于Zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- 转载 [ZooKeeper.net] 3 ZooKeeper的分布式锁
[ZooKeeper.net] 3 ZooKeeper的分布式锁 基于ZooKeeper的分布式锁 源码分享:http://pan.baidu.com/s/1miQCDKk ZooKeeper ...
- Redis与Zookeeper实现分布式锁的区别
Redis实现分布式锁 1.根据lockKey区进行setnx(set not exist,如果key值为空,则正常设置,返回1,否则不会进行设置并返回0)操作,如果设置成功,表示已经获得锁,否则并没 ...
- Zookeeper系列四:Zookeeper实现分布式锁、Zookeeper实现配置中心
一.Zookeeper实现分布式锁 分布式锁主要用于在分布式环境中保证数据的一致性. 包括跨进程.跨机器.跨网络导致共享资源不一致的问题. 1. 分布式锁的实现思路 说明: 这种实现会有一个缺点,即当 ...
- 10分钟看懂!基于Zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
随机推荐
- form表单ajax提交
这里下面有两种 第一种是form表单里面添加了数据,并且含有上传的图片,第二种是from表单中不含有图片 只有普通数据 第一种form表单中包含有图片的类型: <form method=&q ...
- Canvas鼠标点击特效(富强、民主...)、收藏
<script> /* 鼠标特效 */ var a_idx = 0; jQuery(document).ready(function($) { $("body").cl ...
- 关于mybatis拦截器,对结果集进行拦截
因业务需要,需将结果集序列化为json返回,于是,网上找了好久资料,都是关于拦截参数的处理,拦截Sql语法构建的处理,就是很少关于对拦截结果集的处理,于是自己简单的写了一个对结果集的处理, 记录下. ...
- Spider--补充--Requests--session&cookie
# session 与 cookie # 可能大家对session已经比较熟悉了,也大概了解了session的机制和原理,但是我们在做爬虫时如何会运用到session呢,就是接下来要讲到的会话保持. ...
- IP 层收发报文简要剖析6--ip_forward 报文转发
//在函数ip_route_input_slow->ip_mkroute_input注册, /* * IP数据包的转发是由ip_forward()处理,该函数在ip_rcv_finish() * ...
- 04 . Vue组件注册,组件间数据交互,调试工具及组件插槽介绍及使用
vue组件 组件(Component)是 Vue.js 最强大的功能之一. 组件可以扩展 HTML 元素,封装可重用的代码. 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的 ...
- Docker安装Oracle11g
为什么使用docker安装oracle,因为自己搭建配置的话可能时间太久太繁琐等等原因,也因为docker实在太方便了 本文主要是使用docker-compose安装Oracle 11g,因为使用do ...
- day93:flask:
目录 1.HTTP的会话控制 2.Cookie 3.Session 4.请求钩子 5.捕获错误 6.上下文:context 7.Flask-Script 1.HTTP的会话控制 1.什么是会话控制? ...
- 【芯片手册开发】Sil9136音频开发详细分析+源码实战
目录 前言 参考 手册使用+实战 配置 Configuring Audio Using I2S 总结实现 前言 默认在开发了视频方面后 这方面的工作本来可以找技术支持拿个例程参考下,很快就可以的写出来 ...
- 企业级工作流解决方案(十二)--集成Abp和ng-alain--用户身份认证与权限验证
多租户 如果系统需要支持多租户,那么最好事先定义好多租户的存储部署方式,Abp提供了几种方式,根据需要选择,每一个用户身份认证与权限验证都需要完全的隔离 这里设计的权限数据全部存储在缓存中,每个租户单 ...