zookeeper入门篇之分布式锁
文章目录
- 前言
- 非公平锁
- 公平锁
前言
上一篇说过,zookeeper是一个类似文件系统的数据结构,每个节点都可以看做是一个文件目录,也就是说,我们所创建的节点是唯一的,那么分布式锁的原理就是基于这个来的。
代码仓库:https://gitee.com/LIRUIYI/test-zk.git
非公平锁
通过创建节点,并判断节点是否存在实现分布式锁。
- 创建临时节点,如
/lock,临时节点是当出现异常,没有删除导致永久加锁的情况发生 - 当节点不存在,创建节点成功,也就意味着枷锁成功,如果创建失败,那么就是加锁失败
- 其他需要加锁的线程,监听
/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);}
公平锁
相对于非公平锁的实现,这个方式较为复杂一点。
-
先创建一个根节点
/lock -
再在
/lock下创建临时有序节点,有序节点是因为所有需要加锁的节点需要按先来后到的顺序才能公平 -
然后每个有序节点都监听它的前一个节点,如图,当前一个节点被删除,表示解锁了,那么zookeeper会通知到监听的节点,也就是下一个需要加锁的线程

这个在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入门篇之分布式锁
文章目录 前言非公平锁公平锁 前言 上一篇说过,zookeeper是一个类似文件系统的数据结构,每个节点都可以看做是一个文件目录,也就是说,我们所创建的节点是唯一的,那么分布式锁的原理就是基于这个来的。 代码仓库&…...
leetcode解题思路分析(一百四十九)1297 - 1304 题
子串的最大出现次数 给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数: 子串中不同字母的数目必须小于等于 maxLetters 。 子串的长度必须大于等于 minSize 且小于等于 maxSize 。 首先能想到的是从MinSize开始遍历查找&am…...
你的librosa和scikit-learn打架了吗?
被这个问题困扰好久!!!!!!!!!!!!!! 我的原来版本librosa0.7.1 和 scikit-learn1.3.1 一直拆了按,按…...
理解自动驾驶感知技术
理解自动驾驶感知技术 文章目录 什么是自动驾驶感知技术?自动驾驶感知技术的关键组成部分1. 雷达(Radar)2. 摄像头(Camera)3. 激光雷达(Lidar)4. 超声波传感器(Ultrasonic Sensors&a…...
一款简化Python自然语言处理的开源库
迷途小书童 读完需要 3分钟 速读仅需 1 分钟 1 简介 TextBlob 是一个 Python 库,用于处理文本数据的自然语言处理(NLP)任务。它提供了简单且易于使用的 API,使得对文本进行分析、情感分析、词性标注、名词短语提取等任务变得更加简…...
常用Redis界面化软件
对于Redis的操作,前期有过介绍【Centos 下安装 Redis 及命令行操作】。而在Redis的日常开发调试中,可使用可视化软件方便进行操作。 本篇主要介绍Redis可视化的两款工具:Redis Desktop Manager和AnotherRedisDesktopManager。 1、Redis Desk…...
电脑散热——液金散热
目录 1.简介 2.传统硅脂与液金导热区别 3.特点 4.优点 5.为什么液金技术名声不太好 6.使用方法 1.简介 凡是对于电脑基础硬件有所了解的人,都知道硅脂是如今高性能电脑设备中必不可少的东西。芯片表面和散热器接触面,虽然肉眼看上去是非常光滑的金属…...
多线程锁-synchronized字节码分析
从字节码角度分析synchronized实现 javap -c(v附加信息) ***.class 文件反编译 synchronized同步代码块 >>>实现使用的是monitorenter和monitorexit指令 synchronized普通同步方法 >>>调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置…...
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® 新功能
共享和标注 优点:收件人在浏览器中访问共享文 件,无需安装3DEXPERIENCE 平台应用程序。 • 与 SOLIDWORKS 中来自您组织内部或外部的任何人无缝 共享您的设计。 • 直接将评论和标注附加到您的设计作品中,便于立即获得 反馈。 支持 SOLIDWO…...
AMD CPU 虚拟机安装 macos 系统的各虚拟机系统对比
软硬件环境: CPU:AMD R7 7735HS 8核16线程 显卡:AMD R680M 集显 内存:32GB DDR5 硬盘:2TB SSD Windows11 1、VMware Workstation 我用的是17 的版本,使用方便,对于macos 12及以下的安装在需要修改vmx 文…...
php实战案例记录(20)时间比较
在PHP中,有几种常见的方法可以进行时间比较。以下是其中的一些方法: 使用比较运算符:可以使用比较运算符(如小于"<“、大于”>“、小于等于”<“、大于等于”>“、等于”“、不等于”!"等)来比…...
web中缓存的几种方式
看了构建高性能的web站点一书,对其中的集中web缓存进行一个总结 1 应用程序实现的动态页面缓存 应用程序把动态文件生成的html文件缓存到文件服务器,以后用户请求动态文件,直接从文件服务器加载对应的静态缓存的html文件返回给用户ÿ…...
Stable Diffusion生成图片
画质 masterpiece,best quality,illustration,extremely detail CG unity 8k wallpaper,ultra-detailed,depth of field 杰作,最佳质量,插图,极度详细的8K壁纸,超高详细度,景深 画风 Chinese ink painting,water color…...
MySQL增删查改(进阶1)
一、数据库约束 约束:按照一定条件进行规范的做事; 表定义的时候,某些字段保存的数据需要按照一定的约束条件; 1.null约束 字段null:该字段可以为空;not null:该字段不能为空不指定的话就是…...
RabbitMQ-发布订阅模式和路由模式
接上文 RabbitMQ-工作队列 1 发布订阅模式 将之前的配置类内容都替换掉 Bean("fanoutExchange")public Exchange exchange(){//注意这里是fanoutExchangereturn ExchangeBuilder.fanoutExchange("amq.fanout").build();}Bean("yydsQueue1")publ…...
RabbitMQ-主题模式
接上文 RabbitMQ-发布订阅模式和路由模式 1 主题模式 #通配符 代表0个或多个。*通配符 代表 1个或多个 进行测试,修改配置文件 Configuration public class RabbitConfiguration {Bean("topicExchange") //这里使用预置的Topic类型交换机public Exchan…...
阅读文献小技巧
在科研中,文献的阅读是非常重要的一环。对于汇报论文的文献阅读,更是需要有一定的技巧。下面列出一些阅读汇报论文文献的技巧。 1.明确阅读目的和任务。在阅读每篇文献之前,需要明确阅读该文献的目的和任务,例如是否需要了解该领域的最新进展、寻找相关数据或案例等。是为…...
简易的贪吃蛇小游戏(以后或许会更新)C++/C语言
第一版: #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 镜像,要求基于 centos…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
