Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码

章节内容

上节我们完成了:

  • ZooKeeper的Leader选举机制
  • ZooKeeper的选举过程
  • ZooKeeper的ZAB协议

背景介绍

这里是三台公网云服务器,每台 2C4G,搭建一个Hadoop的学习环境,供我学习。
之前已经在 VM 虚拟机上搭建过一次,但是没留下笔记,这次趁着前几天薅羊毛的3台机器,赶紧尝试在公网上搭建体验一下。

  • 2C4G 编号 h121
  • 2C4G 编号 h122
  • 2C2G 编号 h123

分布式锁

出现问题1(单机器)

  • 假设 Redis 里面的某个商品库存为1,此时两个用户同时下单,其中一个下单请求执行到第3步,更新数据库的库存为0,但是第4步还没执行。
  • 而另外一个用户下单执行到了第二步,发现库存还是1,就会继续执行第3步。
  • 但是此时库存已经为0了,所以数据库没有限制,此时会出现超卖的问题。
    在这里插入图片描述

解决方案1

  • 用锁把2、3、4步锁住,让他们执行完后,另一个线程才能够继续执行。
  • 但是由于业务发展迅速,原来的单机已经不能够满足,此时增加一台机器后,会出现更严重的问题。
    在这里插入图片描述

出现问题2(多机器)

假设有两个订单同时执行,分别有两个机器执行,那么这两个请求就是可以同时执行了,这样就依然出现了超卖的问题。

在这里插入图片描述

解决方案2

我们需要使用分布式锁来解决上面出现的问题。
分布式锁的作用就是在整个系统中提供一个全局的、唯一的锁,在分布式系统中每个系统进行相关的操作时都需要获取到该锁,才能够执行相应的操作。

ZK 分布式锁

实现思路

  • 锁就是ZK指定目录下序号最小的临时节点,多个系统的多个线程都要在此目录下创建临时顺序节点,因为ZK会保证节点的顺序性,所以可以利用节点的顺序性进行锁判断。
  • 每个线程都是先创建临时顺序节点,然后获取当前目录下最小的节点(序号),判断最小节点是不是当前节点,如果是那么获取锁成功,如果不是则获取锁失败。
  • 获取锁失败的线程获取当前节点上一个临时顺序节点,并对此节点进行监听,当该节点删除时,代表释放了锁。

流程图

在这里插入图片描述

编写代码

LockTest

package icu.wzk.zk.demo02;public class LockTest {public static void main(String[] args) {for (int i = 0; i < 10; i ++) {// 启动10个new Thread(new LockRunnable()).start();}}static class LockRunnable implements Runnable {@Overridepublic void run() {final ClientTest clientTest = new ClientTest();clientTest.getLock();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}clientTest.deleteLock();}}}

ClientTest

package icu.wzk.zk.demo02;import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class ClientTest {private ZkClient zkClient = new ZkClient("h121.wzk.icu:2181,h122.wzk.icu:2181,h123.wzk.icu:2181");String beforeNodePath;String currentNodePath;CountDownLatch countDownLatch = null;public ClientTest() {synchronized (ClientTest.class) {if (!zkClient.exists("/lock")) {zkClient.createPersistent("/lock");}}}public boolean tryGetLock() {if (null == currentNodePath || currentNodePath.isEmpty()) {currentNodePath = zkClient.createEphemeralSequential("/lock/", "lock");}final List<String> childs = zkClient.getChildren("/lock");Collections.sort(childs);final String minNode = childs.get(0);if (currentNodePath.equals("/lock/" + minNode)) {return true;} else {final int i = Collections.binarySearch(childs, currentNodePath.substring("/lock/".length()));String lastNodeChild = childs.get(i - 1);beforeNodePath = "/lock/" + lastNodeChild;}return false;}public void waitForLock() {final IZkDataListener iZkDataListener = new IZkDataListener() {@Overridepublic void handleDataChange(String dataPath, Object data) throws Exception {//}@Overridepublic void handleDataDeleted(String dataPath) throws Exception {countDownLatch.countDown();}};zkClient.subscribeDataChanges(beforeNodePath, iZkDataListener);if (zkClient.exists(beforeNodePath)) {countDownLatch = new CountDownLatch(1);try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}}zkClient.unsubscribeDataChanges(beforeNodePath, iZkDataListener);}public void deleteLock() {if (zkClient != null) {zkClient.delete(currentNodePath);zkClient.close();}}public void getLock() {final String threadName = Thread.currentThread().getName();if (tryGetLock()) {System.out.println(threadName + ": 获取到了锁!");} else {System.out.println(threadName + ": 没有获取到锁!");waitForLock();// 自己调用自己getLock();}}}

运行结果

在这里插入图片描述

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

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

相关文章

【Linux】多线程_9

文章目录 九、多线程10. 线程池 未完待续 九、多线程 10. 线程池 这里我没实现一些 懒汉单例模式 的线程池&#xff0c;并且包含 日志打印 的线程池&#xff1a; Makefile&#xff1a; threadpool:Main.ccg -o $ $^ -stdc11 -lpthread .PHONY:clean clean:rm -f threadpoolT…

element ui中el-form-item的属性rules的用法

目录 el-form-item的属性rules的用法 栗子 总结 实践应用 一、 定义静态的校验规则 二、定义动态的校验规则 el-form-item的属性rules的用法 在学习element ui 的Form表单组件时&#xff0c;学到el-form-item也有rules属性&#xff0c;但是对应这个属性如何使用&#x…

Databend 开源周报第 153 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend。 支持必须更改密码…

Adobe Photoshop 2024 25.9.1 Win/Mac PS2024最新中文学习版

Adobe Photoshop 2024&#xff0c;简称PS&#xff0c;目前最强的图片处理合成软件,PS提供了广泛的工具和功能&#xff0c;包括画笔、铅笔、颜色替换、混合器画笔等绘画工具&#xff0c;以及裁剪、透视变形、智能修复画笔等编辑工具。用户可以使用这些工具进行图片编辑、合成、校…

旅游数据可视化:免费工具让复杂数据变得简单易懂

随着旅游业的蓬勃发展&#xff0c;海量的数据如同繁星点点&#xff0c;记录着每一位旅者的足迹与偏好。然而&#xff0c;如何将这些复杂的数据转化为直观、易懂的信息&#xff0c;为旅游企业精准决策、为消费者提供更加个性化的服务&#xff0c;成为了行业内外共同关注的焦点。…

vue2+antd实现表格合并;excel效果

效果图 一、html <template><div><a-table :columns"columns" :dataSource"dataSource" rowKey"id" :pagination"false" bordered><template slot"content1" slot-scope"text">{{text}}…

JuiceFS缓存特性

缓存 对于一个由对象存储和数据库组合驱动的文件系统&#xff0c;缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据可以提前或者异步载入缓存&#xff0c;再由客户端在后台与远端服务交互执行异步上传或预取数据。相比直接与远端服务交互&#xff0c;采用缓存技…

图片如何去水印,PS 图片去水印的几种常见方法

在数字图像的世界里&#xff0c;水印常常被用来标识版权或防止未经授权的使用&#xff0c;但有时它们却成为了美观的障碍。无论是出于个人偏好还是专业需求&#xff0c;去除图片上的水印已经成为一项常见的任务。 Adobe Photoshop 作为行业标准的图像编辑软件&#xff0c;提供…

热门软件缺陷管理工具2024:专业评测与建议

国内外主流的10款软件缺陷管理工具软件对比&#xff1a;PingCode、Worktile、禅道、Tapd、Teambition、Tower、JIRA、Bugzilla、MantisBT、Trac。 在软件开发过程中&#xff0c;管理缺陷和漏洞常常成为一项挑战&#xff0c;尤其是在项目规模庞大时。选择一个高效的软件缺陷管理…

C语言------指针讲解(2)

目录 一、数组名的理解 二、使用指针访问数组 三、一维数组传参的本质 四、冒泡排序 五、二级指针 六、指针数组 七、指针数组模拟二维数组 一、数组名的理解 通过学习&#xff0c;我们知道&#xff1a;数组名和数组首元素的地址打印出来的结果一模一样&#xff0c;数组…

深度刨析程序中的指针

前面我们已经学习过了指针的一下性质&#xff1a; 指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识的一块内存空间指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09;指针是有类型&#xff0c;指针的类型决定了指针的加减整数的步长&…

SQL 中的 EXISTS 子句:探究其用途与应用

目录 EXISTS 子句简介语法 EXISTS 与 NOT EXISTSEXISTS 子句的工作原理实际应用场景场景一&#xff1a;筛选存在关联数据的记录场景二&#xff1a;优化查询性能 EXISTS 与其他 SQL 结构的比较EXISTS vs. JOINEXISTS vs. IN 多重 EXISTS 条件在 UPDATE 语句中使用 EXISTS常见问题…

Maven学习—如何在IDEA中配置Maven?又如何创建Maven工程?(详细攻略)

目录 前言 1.在IDEA中配置Maven 2.创建Maven项目 &#xff08;1&#xff09;Maven&#xff1a;创建普通Maven工程 &#xff08;2&#xff09;Maven Archetype&#xff1a;创建Maven模板工程 前言 本篇博客将详细的介绍在IDEA中如何配置Maven&#xff0c;以及如何创建一个Ma…

分布式 I/O 系统 BL200 Modbus TCP 耦合器

BL200 耦合器是一个数据采集和控制系统&#xff0c;基于强大的 32 位微处理器设计&#xff0c;采用 Linux 操作系统&#xff0c;支持 Modbus 协议&#xff0c;可以快速接入现场 PLC、SCADA 以及 ERP 系统&#xff0c; 内置逻辑控制、边缘计算应用&#xff0c;适用于 IIoT 和工业…

园区道路车辆智能管控视频解决方案,打造安全畅通的园区交通环境

一、背景需求分析 随着企业园区的快速发展和扩张&#xff0c;道路车辆管理成为了保障园区秩序、提升运营效率及确保员工安全的重要任务。针对这一需求&#xff0c;旭帆科技TSINGSEE青犀提出了一种企业园区道路车辆管控的解决方案&#xff0c;通过整合视频监控、智能识别等技术…

Qt6 OpenCV4视频监控系统项目源码解析——附源码及编译运行步骤

很多刚毕业&#xff0c;或者想着转行到C Qt方向的小伙伴&#xff0c;平时可能拿不出比较像样的项目。这里你可要好好收藏啦。自己拿回去好好改改&#xff0c;就可以成为自己的项目经历了。祝各位找工作顺利呀。 好了。废话不多说。 这个项目架构采用的是MVC架构&#xff0c;结…

Porfinet从转DeviceNet从总线协议转换网关

产品功能 1. 远创智控YC-DNT-PN型是Porfinet从转Devicenet从工业级Porfinet 网关。‌这种网关设备允许将Porfinet网络中的设备连接到Devicenet网络中&#xff0c;‌从而实现不同工业通信协议之间的互操作性。‌这些网关设备通常具有两个以太网接口&#xff0c;‌分别用于连接Po…

STM32智能楼宇照明系统教程

目录 引言环境准备智能楼宇照明系统基础代码实现&#xff1a;实现智能楼宇照明系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;楼宇照明管理与优化问题解决方案与优化收尾与总结 1. 引言 智能楼宇照明系…

【verilog语法】$clog2(IEEE Std 1364-2005)

一、前言 在进行Verilog设计时&#xff0c;有时需要根据内存大小来计算地址的位宽&#xff0c;或者根据变量的值来确定变量的位宽&#xff0c;这时可以自己编写相关的可综合函数&#xff0c;或者verilog-2005起开始支持的$clog2系统函数。 二、自己编写的function function i…

代码规范性

代码规范性 命名规范代码格式注释代码结构异常处理代码复用代码审查空格的用法代码示例 命名规范 ​ 1、变量和函数名&#xff1a;使用驼峰命名法&#xff08;camelCase&#xff09;&#xff0c;如userName、getUserInfo。 ​ 2、常量&#xff1a;使用全大写字母&#xff0c;…