当前位置: 首页 > news >正文

zookeeper入门篇之分布式锁

文章目录

  • 前言
  • 非公平锁
  • 公平锁

前言

上一篇说过,zookeeper是一个类似文件系统的数据结构,每个节点都可以看做是一个文件目录,也就是说,我们所创建的节点是唯一的,那么分布式锁的原理就是基于这个来的。

代码仓库:https://gitee.com/LIRUIYI/test-zk.git

非公平锁

通过创建节点,并判断节点是否存在实现分布式锁。

  1. 创建临时节点,如/lock,临时节点是当出现异常,没有删除导致永久加锁的情况发生
  2. 当节点不存在,创建节点成功,也就意味着枷锁成功,如果创建失败,那么就是加锁失败
  3. 其他需要加锁的线程,监听/lock节点(get -w /lock),当节点/lock删除后,zookeeper会通知到监听的节点

这种方式的加锁,不能保证需要加锁的线程能得到锁的概率一样,他们是随机的,有可能最先排队的加锁线程,到最后都不能得到锁,这就是非公平锁。

以原始客户端实现非公平锁:

这里zookeeper地址和上面不一样,因为之前是桥接模式,自动获取的,有时ip会变动,所以改NAT模式,设定了静态ip

package com.liry.zk;import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;/*** 分布式锁 - 非公平锁实现** @author ALI* @since 2022/12/25*/
@Slf4j
public class NonfairSyncLock {private static final String CONNECT_STR = "192.168.17.128:2181";private static final int TIME_OUT = 30000;private static final String LOCK_PATH = "/lock";private static ZooKeeper zookeeper = null;/*** 获取客户端*/public static ZooKeeper getClient() throws IOException, InterruptedException {synchronized (LOCK_PATH) {final CountDownLatch latch = new CountDownLatch(1);if (zookeeper == null) {Watcher startWatcher = watchedEvent -> {if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected) {log.info("与zookeeper建立连接");latch.countDown();}};zookeeper = new ZooKeeper(CONNECT_STR, TIME_OUT, startWatcher);latch.await();} else if (zookeeper.getState() != ZooKeeper.States.CONNECTED) {latch.await();}}return zookeeper;}/*** 加锁*/public void lock() {while (true) {if (tryLock()) {return;}// 加锁失败,增加监听,然后阻塞try {watch();} catch (Exception e) {throw new RuntimeException(e);}}}/*** 解锁*/public void unlock() {try {getClient().delete(LOCK_PATH, -1);} catch (Exception e) {throw new RuntimeException(e);}}/*** 尝试加锁*/private boolean tryLock() {try {getClient().create(LOCK_PATH, "lock".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);} catch (Exception e) {log.error("加锁失败");return false;}return true;}/*** 监听锁节点* 当节点存在时,线程阻塞,当节点不存在,直接退出监听*/private void watch() throws InterruptedException, KeeperException, IOException {CountDownLatch latch = new CountDownLatch(1);Watcher dataWatch = event -> {if (event.getType() == Watcher.Event.EventType.NodeDeleted) {latch.countDown();}};try {getClient().getData(LOCK_PATH, dataWatch, null);} catch (KeeperException.NoNodeException e) {// 当创建监听时,节点不存在,说明有线程解锁了,那么直接退出,监听步骤,去争抢锁return;}latch.await();}}
    static int count = 0;public static void main(String[] args) throws InterruptedException {nonFairLock();}private static void nonFairLock() throws InterruptedException {NonfairSyncLock lock = new NonfairSyncLock();CountDownLatch latch = new CountDownLatch(1000);List<Thread> threadList = IntStream.range(0, 1000).mapToObj(d -> new Thread(() -> {lock.lock();count += 1;latch.countDown();lock.unlock();}, "线程-" + d)).collect(Collectors.toList());threadList.forEach(Thread::start);latch.await();System.out.println("最终结果应是1000:" + count);}

公平锁

相对于非公平锁的实现,这个方式较为复杂一点。

  1. 先创建一个根节点/lock

  2. 再在/lock下创建临时有序节点,有序节点是因为所有需要加锁的节点需要按先来后到的顺序才能公平

  3. 然后每个有序节点都监听它的前一个节点,如图,当前一个节点被删除,表示解锁了,那么zookeeper会通知到监听的节点,也就是下一个需要加锁的线程

    image-20221225132210169

这个在curator中已经有实现了,分布式锁不局限于zookeeper,了解其原理就行

static int count = 0;public static void main(String[] args) throws InterruptedException {
//        nonFairLock();fairLock();}private static void fairLock() throws InterruptedException {// 使用curator客户端RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);CuratorFramework client = CuratorFrameworkFactory.builder().connectString("92.168.17.128:2181").sessionTimeoutMs(3000).connectionTimeoutMs(3000).retryPolicy(retryPolicy).build();client.start();InterProcessMutex lock = new InterProcessMutex(client, "/lock");CountDownLatch latch = new CountDownLatch(1000);List<Thread> threadList = IntStream.range(0, 1000).mapToObj(d -> new Thread(() -> {try {lock.acquire();} catch (Exception e) {throw new RuntimeException(e);}count += 1;latch.countDown();try {lock.release();} catch (Exception e) {throw new RuntimeException(e);}}, "线程-" + d)).collect(Collectors.toList());threadList.forEach(Thread::start);latch.await();System.out.println("最终结果应是1000:" + count);}

相关文章:

zookeeper入门篇之分布式锁

文章目录 前言非公平锁公平锁 前言 上一篇说过&#xff0c;zookeeper是一个类似文件系统的数据结构&#xff0c;每个节点都可以看做是一个文件目录&#xff0c;也就是说&#xff0c;我们所创建的节点是唯一的&#xff0c;那么分布式锁的原理就是基于这个来的。 代码仓库&…...

leetcode解题思路分析(一百四十九)1297 - 1304 题

子串的最大出现次数 给你一个字符串 s &#xff0c;请你返回满足以下条件且出现次数最大的 任意 子串的出现次数&#xff1a; 子串中不同字母的数目必须小于等于 maxLetters 。 子串的长度必须大于等于 minSize 且小于等于 maxSize 。 首先能想到的是从MinSize开始遍历查找&am…...

你的librosa和scikit-learn打架了吗?

被这个问题困扰好久&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 我的原来版本librosa0.7.1 和 scikit-learn1.3.1 一直拆了按&#xff0c;按…...

理解自动驾驶感知技术

理解自动驾驶感知技术 文章目录 什么是自动驾驶感知技术&#xff1f;自动驾驶感知技术的关键组成部分1. 雷达&#xff08;Radar&#xff09;2. 摄像头&#xff08;Camera&#xff09;3. 激光雷达&#xff08;Lidar&#xff09;4. 超声波传感器&#xff08;Ultrasonic Sensors&a…...

一款简化Python自然语言处理的开源库

迷途小书童 读完需要 3分钟 速读仅需 1 分钟 1 简介 TextBlob 是一个 Python 库&#xff0c;用于处理文本数据的自然语言处理&#xff08;NLP&#xff09;任务。它提供了简单且易于使用的 API&#xff0c;使得对文本进行分析、情感分析、词性标注、名词短语提取等任务变得更加简…...

常用Redis界面化软件

对于Redis的操作&#xff0c;前期有过介绍【Centos 下安装 Redis 及命令行操作】。而在Redis的日常开发调试中&#xff0c;可使用可视化软件方便进行操作。 本篇主要介绍Redis可视化的两款工具&#xff1a;Redis Desktop Manager和AnotherRedisDesktopManager。 1、Redis Desk…...

电脑散热——液金散热

目录 1.简介 2.传统硅脂与液金导热区别 3.特点 4.优点 5.为什么液金技术名声不太好 6.使用方法 1.简介 凡是对于电脑基础硬件有所了解的人&#xff0c;都知道硅脂是如今高性能电脑设备中必不可少的东西。芯片表面和散热器接触面&#xff0c;虽然肉眼看上去是非常光滑的金属…...

多线程锁-synchronized字节码分析

从字节码角度分析synchronized实现 javap -c(v附加信息) ***.class 文件反编译 synchronized同步代码块 >>>实现使用的是monitorenter和monitorexit指令 synchronized普通同步方法 >>>调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置&#xf…...

SpringCloud学习笔记-Eureka的服务拉取

假设是OrderService里面拉取Eureka的服务之一User Service 1.依然需要在该服务里面引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependenc…...

COLLABORATIVE DESIGNER FOR SOLIDWORKS® 新功能

共享和标注 优点&#xff1a;收件人在浏览器中访问共享文 件&#xff0c;无需安装3DEXPERIENCE 平台应用程序。 • 与 SOLIDWORKS 中来自您组织内部或外部的任何人无缝 共享您的设计。 • 直接将评论和标注附加到您的设计作品中&#xff0c;便于立即获得 反馈。 支持 SOLIDWO…...

AMD CPU 虚拟机安装 macos 系统的各虚拟机系统对比

软硬件环境&#xff1a; CPU:AMD R7 7735HS 8核16线程 显卡&#xff1a;AMD R680M 集显 内存&#xff1a;32GB DDR5 硬盘&#xff1a;2TB SSD Windows11 1、VMware Workstation 我用的是17 的版本&#xff0c;使用方便&#xff0c;对于macos 12及以下的安装在需要修改vmx 文…...

php实战案例记录(20)时间比较

在PHP中&#xff0c;有几种常见的方法可以进行时间比较。以下是其中的一些方法&#xff1a; 使用比较运算符&#xff1a;可以使用比较运算符&#xff08;如小于"<“、大于”>“、小于等于”<“、大于等于”>“、等于”“、不等于”!"等&#xff09;来比…...

web中缓存的几种方式

看了构建高性能的web站点一书&#xff0c;对其中的集中web缓存进行一个总结 1 应用程序实现的动态页面缓存 应用程序把动态文件生成的html文件缓存到文件服务器&#xff0c;以后用户请求动态文件&#xff0c;直接从文件服务器加载对应的静态缓存的html文件返回给用户&#xff…...

Stable Diffusion生成图片

画质 masterpiece,best quality,illustration,extremely detail CG unity 8k wallpaper,ultra-detailed,depth of field 杰作&#xff0c;最佳质量&#xff0c;插图&#xff0c;极度详细的8K壁纸&#xff0c;超高详细度&#xff0c;景深 画风 Chinese ink painting,water color…...

MySQL增删查改(进阶1)

一、数据库约束 约束&#xff1a;按照一定条件进行规范的做事&#xff1b; 表定义的时候&#xff0c;某些字段保存的数据需要按照一定的约束条件&#xff1b; 1.null约束 字段null&#xff1a;该字段可以为空&#xff1b;not null&#xff1a;该字段不能为空不指定的话就是…...

RabbitMQ-发布订阅模式和路由模式

接上文 RabbitMQ-工作队列 1 发布订阅模式 将之前的配置类内容都替换掉 Bean("fanoutExchange")public Exchange exchange(){//注意这里是fanoutExchangereturn ExchangeBuilder.fanoutExchange("amq.fanout").build();}Bean("yydsQueue1")publ…...

RabbitMQ-主题模式

接上文 RabbitMQ-发布订阅模式和路由模式 1 主题模式 #通配符 代表0个或多个。*通配符 代表 1个或多个 进行测试&#xff0c;修改配置文件 Configuration public class RabbitConfiguration {Bean("topicExchange") //这里使用预置的Topic类型交换机public Exchan…...

阅读文献小技巧

在科研中,文献的阅读是非常重要的一环。对于汇报论文的文献阅读,更是需要有一定的技巧。下面列出一些阅读汇报论文文献的技巧。 1.明确阅读目的和任务。在阅读每篇文献之前,需要明确阅读该文献的目的和任务,例如是否需要了解该领域的最新进展、寻找相关数据或案例等。是为…...

简易的贪吃蛇小游戏(以后或许会更新)C++/C语言

第一版&#xff1a; #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <windows.h>#define WIDTH 20 #define HEIGHT 20int gameOver; int score; int x, y; // 蛇头的坐标 int fruitX, fruitY; // 食物的坐标 int tailX[100], t…...

23云计算全国职业技能大赛容器云-容器编排

erp 2.2.1 容器化部署 MariaDB [0.5 分]2.2.2 容器化部署 Redis [0.5 分]2.2.3 容器化部署 Nginx [0.5 分]2.2.4 容器化部署 ERP[0.5 分]2.2.5 编排部署 ERP管理系统[1 分] 2.2.1 容器化部署 MariaDB [0.5 分] 编写 Dockerfile 文件构建 mysql 镜像&#xff0c;要求基于 centos…...

别只看成功率!拆解AlphaFold3在抗体对接中那60%的失败案例

AlphaFold3抗体对接失败的深层解析&#xff1a;60%案例背后的技术挑战与突破路径 当AlphaFold3&#xff08;AF3&#xff09;在抗体-抗原对接领域取得8.9%的高精度成功率时&#xff0c;科学界为之振奋。但鲜少有人关注到&#xff0c;在单种子采样条件下&#xff0c;这一系统仍有…...

vLLM-v0.17.1保姆级教程:vLLM + Weights Biases 实验跟踪实践

vLLM-v0.17.1保姆级教程&#xff1a;vLLM Weights & Biases 实验跟踪实践 1. vLLM框架简介 vLLM是一个专注于大语言模型推理和服务的开源库&#xff0c;以其出色的性能和易用性在开发者社区中广受欢迎。这个项目最初由加州大学伯克利分校的天空计算实验室发起&#xff0…...

FUTURE POLICE语音模型重装系统后快速恢复部署指南

FUTURE POLICE语音模型重装系统后快速恢复部署指南 重装系统这事儿&#xff0c;对开发者来说&#xff0c;有时候就跟电脑的“大扫除”一样&#xff0c;图个干净利落。但扫除完&#xff0c;看着空空如也的桌面和命令行&#xff0c;要重新把那些吃饭的家伙——比如你正在跑的FUT…...

TinyCheck开发指南:从源码结构到核心类设计,理解网络安全检测平台架构

TinyCheck开发指南&#xff1a;从源码结构到核心类设计&#xff0c;理解网络安全检测平台架构 【免费下载链接】TinyCheck TinyCheck allows you to easily capture network communications from a smartphone or any device which can be associated to a Wi-Fi access point …...

【Python】利用Python实现微信公众号文章定时自动发布

1. 微信公众号自动发布的基础原理 很多人可能不知道&#xff0c;微信公众号其实提供了完整的开发者接口&#xff0c;允许我们通过代码来管理内容。这就像给你的公众号装了一个遥控器&#xff0c;不用每天手动登录后台点点戳戳。我最早发现这个功能时&#xff0c;简直像发现了新…...

nfc-list使用教程

nfc-list 是 Kali Linux 中基于 libnfc 库&#xff08;开源 NFC 开发框架&#xff09;的基础 NFC/RFID 设备检测工具&#xff0c;核心功能是扫描并列出当前连接的 NFC 读卡器设备&#xff0c;以及贴近读卡器的 NFC 卡片&#xff08;或标签&#xff09;的详细信息&#xff0c;包…...

【esp-idf调试问题-代码为提前配置工程,配网wedsocket服务】

esp-idf调试问题-配网wedsocket服务一、提示分区表错误&#xff0c;没有配置自己的编写的分区表。menuconfig 配置分区表步骤 1&#xff1a;打开配置菜单 在项目根目录执行&#xff1a;步骤 2&#xff1a;选择分区表类型 在 Partition Table → Partition Table 中可选&#xf…...

十字头零件的机械加工工艺规程及工装夹具设计 (论文+CAD图纸+任务书+过程卡+工序卡+外文翻译+参考文献……)

十字头零件作为机械传动系统中的关键构件&#xff0c;其加工精度直接影响设备运行的稳定性与寿命。制定科学合理的机械加工工艺规程及配套工装夹具设计方案&#xff0c;是确保零件质量、提升加工效率的核心环节。工艺规程需系统规划从毛坯准备到成品检验的全流程&#xff0c;涵…...

KRM库:Arduino嵌入式运动控制的安全映射与非阻塞调度

1. KRM库概述&#xff1a;面向嵌入式运动控制的Arduino实用工具集KRM&#xff08;Koval Robotics & Motion&#xff09;是一个专为Arduino平台设计的轻量级底层工具库&#xff0c;其核心定位并非通用算法封装&#xff0c;而是聚焦于机器人与机电控制系统开发中高频、重复、…...

Kubernetes与Istio服务网格最佳实践

Kubernetes与Istio服务网格最佳实践 1. Istio服务网格核心概念 1.1 什么是服务网格 服务网格是一种专门用于处理服务间通信的基础设施层&#xff0c;它负责在现代云原生应用的复杂服务拓扑中可靠地传递请求。 1.2 Istio架构组件 控制平面&#xff1a;包含Pilot、Galley、Citade…...