分布式锁3: zk实现分布式锁4 使用临时顺序节点+watch监听+可重入(threadLocal)

一  zk实现分布式锁的可重入性

1.1 使用ThreadLocal属性

引入ThreadLocal线程局部变量保证zk分布式锁的可重入性。

1.2 关键代码说明

1.3 代码

1.3.1 初始化客户端

1.3.2 分布式锁代码

package com.atguigu.distributed.lock.config;import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.*;import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;/*** @ClassName: ZkDistriubtedTHLock* @Description: TODO* @Author: admin* @Date: 2024/01/06 16:07:04 * @Version: V1.0**/
public class ZkDistriubtedTHLock  implements Lock {private static final String ROOT_PATH = "/d-zk";private String path;private ZooKeeper zooKeeper;private static final ThreadLocal<Integer> THREAD_LOCAL = new ThreadLocal<>();public ZkDistriubtedTHLock(ZooKeeper zooKeeper,String lockName) {try {this.zooKeeper = zooKeeper;if (THREAD_LOCAL.get() == null || THREAD_LOCAL.get() == 0){this.path = zooKeeper.create(ROOT_PATH + "/" + lockName + "-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);}} catch (KeeperException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void lock() {Integer flag = THREAD_LOCAL.get();if (flag != null && flag > 0) {THREAD_LOCAL.set(flag + 1);return;}else{try {String preNode = getPreNode(path);// 如果该节点没有前一个节点,说明该节点时最小节点,放行执行业务逻辑if (StringUtils.isEmpty(preNode)){THREAD_LOCAL.set(1);return ;} else {CountDownLatch countDownLatch = new CountDownLatch(1);if (this.zooKeeper.exists(ROOT_PATH + "/" + preNode, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("当前节点=="+path+" 前一个节点:"+ROOT_PATH + "/" + preNode);countDownLatch.countDown();}}) == null) {System.out.println("监听。。。");THREAD_LOCAL.set(1);return;}// 阻塞。。。。countDownLatch.await();System.out.println("wait。。。");THREAD_LOCAL.set(1);return;}} catch (Exception e) {e.printStackTrace();// 重新检查。是否获取到锁try {Thread.sleep(200);} catch (InterruptedException ex) {ex.printStackTrace();}lock();}}}@Overridepublic void lockInterruptibly() throws InterruptedException {}@Overridepublic boolean tryLock() {return false;}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return false;}/*** 获取指定节点的前节点* @param path* @return*/private String getPreNode(String path){try {// 获取当前节点的序列化号Long curSerial = Long.valueOf(StringUtils.substringAfterLast(path, "-"));// 获取根路径下的所有序列化子节点List<String> nodes = this.zooKeeper.getChildren(ROOT_PATH, false);// 判空if (CollectionUtils.isEmpty(nodes)){return null;}// 获取前一个节点Long flag = 0L;String preNode = null;for (String node : nodes) {// 获取每个节点的序列化号Long serial = Long.valueOf(StringUtils.substringAfterLast(node, "-"));if (serial < curSerial && serial > flag){flag = serial;preNode = node;}}return preNode;} catch (KeeperException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}return null;}@Overridepublic void unlock() {try {THREAD_LOCAL.set(THREAD_LOCAL.get() - 1);if (THREAD_LOCAL.get() == 0) {this.zooKeeper.delete(path, 0);THREAD_LOCAL.remove();}} catch (InterruptedException e) {e.printStackTrace();} catch (KeeperException e) {e.printStackTrace();}}@Overridepublic Condition newCondition() {return null;}
}

1.3.3 service

1.3.4 controller

1.4 测试

1.4.1 nginx多节点代理

1.服务

2.nginx

1.4.2 jemeter测试

3.jemeter

4.数据库前后

5.服务节点日志

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/326482.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《剑指 Offer》专项突破版 - 面试题 3 :前 n 个数字二进制形式中 1 的个数(C++ 实现)

目录 前言 方法一 方法二 方法三 前言 题目链接&#xff1a;338. 比特位计数 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 输入一个非负数 n&#xff0c;请计算 0 到 n 之间每个数字的二进制形式中 1 的个数&#xff0c;并输出一个数组。例如&#xff0…

thingsboard规则节点功能记录(自用)

本文是对【ThingsBoard源码级分析规则节点使用第一季】 https://www.bilibili.com/video/BV1CT411e7vt/?p4&share_sourcecopy_web&vd_source9a5ca7ed3cff97385fdab4b6188e485c 学习的一些记录&#xff0c;加深自己的理解&#xff0c;在此声明。 asset profile switch…

跨国制造业组网方案解析,如何实现总部-分支稳定互联?

既要控制成本&#xff0c;又要稳定高效&#xff0c;可能吗&#xff1f; 在制造企业积极向“智造”发展、数字化转型的当下&#xff0c;物联网、人工智能、机器人等新型设备加入到生产、管理环节&#xff0c;为企业内部数据传输提出了更高的要求。而当企业规模扩大&#xff0c;数…

用ChatGPT方式编程!GitHub Copilot Chat全面开放使用

全球著名开源分享平台GitHub在官网宣布&#xff0c;经过几个月多轮测试的GitHub Copilot Chat&#xff0c;全面开放使用&#xff0c;一个用ChatGPT方式写代码的时代来啦&#xff01; 据悉&#xff0c;Copilot Chat是基于OpenAI的GPT-4模型&#xff0c;再结合其海量、优质的代码…

小红书 X WSDM 2024「对话式多文档问答挑战赛」火热开赛!

基于大语言模型&#xff08;LLM&#xff09;的对话问答机器人&#xff0c;已经成为当前人工智能领域学术界和工业界共同关注的的热门研究方向之一。在对话过程中&#xff0c;为大模型引入搜索结果&#xff0c;进行检索增强的生成&#xff08;Retrieval Augmented Generation&am…

NVIDIA Jetpack6.0DP使用过程中的问题

Jetpack6.0DP是2023年12月才发布&#xff0c; 操作系统使用了ubuntu 22.04&#xff0c; gcc是11.4&#xff0c;版本都很高&#xff0c; 用起来还存在一些问题 无法使用jtop https://forums.developer.nvidia.com/t/jtop-no-longer-works-on-jp-6-0-dp/275215 使用$ sudo -H p…

写给自己的CSDN博客之旅-如何从过程中获取价值-

勇于尝试 一个普通人如何在竞争越来越激烈的现代社会找到安身立业的方式&#xff1f; 作为一个注册CSDN已经有19年的老人&#xff0c;这些年失败的经历实在是太多太多了。 虽然注册CSDN很早&#xff0c;但是写博客确是在工作之后&#xff0c;也就是2015年。 在此之前有很多失…

什么?谁?w (who what)

文章目录 什么&#xff1f;谁&#xff1f;w (who & what)默认的显示不显示标题行简洁模式显示更多信息 什么&#xff1f;谁&#xff1f;w (who & what) w可以认为是加强版的who&#xff0c;果然越简洁越强大&#xff0c;就比如less比more是功能更多的。 w不仅可以显示…

Linux 上 Nginx 配置访问 web 服务器及配置 https 访问配置过程记录

目录 一、前言说明二、配置思路三、开始修改配置四、结尾 一、前言说明 最近自己搭建了个 Blog 网站&#xff0c;想把网站部署到服务器上面&#xff0c;本文记录一下搭建过程中 Nginx 配置请求转发的过程。 二、配置思路 web项目已经在服务器上面运行起来了&#xff0c;运行的端…

[概率论]重生至期末考前一个月看我如何力挽狂澜(下)

课本为《概率论与数理统计》ISBN 978-7-301-29547-2&#xff0c;此次整理4-8章的内容。 第四章 随机变量的数字特征 期望 频率具有波动性&#xff0c;概率具有稳定性。 离散型 设X是离散型随机变量&#xff0c;其分布律为&#xff1a;P{Xxk}pk ,k0,1,2,…… 两点分布 E(X)…

JavaScrip-初识JavaScript-知识点

初识JavaScript 编程基础编程计算机语言标记语言编译器&解释器 计算机基础计算机组成数据存储数据存储单位程序运行 认识JavaScript什么是JavaScriptJavaScript作用HTML&CSS&JavaScript的关系浏览器执行JavaScript过程JavaScript的组成JavaScript初体验 JavaScript…

轻松获取CHATGPT API:免费、无验证、带实例

免费获取和使用ChatGPT API的方法 快速开始&#xff1a;视频教程 章节一&#xff1a;GPT-API-Free开源项目介绍 GPT-API-Free 是一个开源项目&#xff0c;它提供了一个中转API KEY&#xff0c;使用户能够调用多个GPT模型&#xff0c;包括gpt-3.5-turbo、embedding和gpt-4。这…