分布式锁zookeeper实现详解原理及落地方案

news2024/12/29 1:49:20

吐血推荐:最近整理之前面试BAT的材料,写了一份《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
领取方法: Java面试BATJ通关手册

介绍

当一个应用程序需要在分布式系统中对共享资源进行访问和修改时,就需要考虑并发访问和操作的问题。例如,多个服务实例同时尝试对同一数据库表中的记录进行更新,可能会导致更新操作的冲突和数据不一致的问题。

分布式锁是一种解决并发问题的机制,它可以协调分布式系统中的多个服务实例对共享资源的访问,保证在任意时刻只有一个实例能够对资源进行操作,避免了并发操作引起的数据不一致性和冲突问题。因此,分布式锁在分布式系统中具有非常重要的作用和必要性。

除此之外,分布式锁还可以用于:

  • 控制访问次数:在一些需要频繁调用的接口或方法上,使用分布式锁可以控制对其访问的频率,避免被频繁调用而导致系统的负载压力过大。

  • 避免重复执行:对于一些需要确保只能被执行一次的操作,如数据初始化、资源清理等,使用分布式锁可以避免重复执行。

  • 协调多个服务实例:当多个服务实例需要协同工作时,使用分布式锁可以确保每个实例在特定的时刻只执行一定的任务,从而保证整个系统的正确性和一致性。

因此,分布式锁的作用和必要性在分布式系统中是不可替代的。而ZooKeeper作为分布式协调服务,提供了实现分布式锁的解决方案。

ZooKeeper简介

ZooKeeper是一个分布式协调服务,由Apache开发。其主要特点是提供高性能、高可用、严格顺序访问、数据持久化等功能,被广泛应用于分布式应用场景,如分布式锁、分布式队列等。

ZooKeeper的数据模型基于ZooKeeper服务的文件系统,支持类似于Unix文件系统的目录结构,使用节点来表示目录和文件,这些节点都可以存储数据。每个节点都有唯一的路径,通过这个路径来访问节点。节点分为持久节点和临时节点,持久节点在创建后一直存在,而临时节点在创建它的客户端会话结束时被删除。

ZooKeeper的使用场景包括:

  • 配置管理

  • 分布式锁

  • 分布式队列

  • 集群管理

  • 命名服务

分布式锁的实现

当多个进程或线程同时访问共享资源时,为了避免数据混乱、重复处理等问题,我们需要引入分布式锁机制。ZooKeeper正好提供了一种基于节点状态变化来实现分布式锁的解决方案。

下面是使用ZooKeeper实现分布式锁的具体步骤:

  1. 在ZooKeeper上创建一个用于锁定的节点(通常是顺序临时节点),表示这个锁当前被某个进程占用。

  2. 如果当前进程需要获取锁,则在该节点的父节点上添加一个临时顺序节点,表示当前进程请求获取锁,并获取所有子节点的列表。

  3. 判断当前进程创建的节点是否是所有子节点中序号最小的节点。如果是,则当前进程获取到了锁;如果不是,则说明还有其他进程在等待锁,当前进程需要监听比自己序号小的那个节点的删除事件。

  4. 如果比自己序号小的节点被删除了,当前进程重新获取所有子节点的列表,判断自己是否是序号最小的节点。如果是,则获取到了锁,否则重复上述步骤。

  5. 如果当前进程完成了对共享资源的操作,需要释放锁,即删除节点。

需要注意的是,当一个进程获取到了锁,一定要确保在释放锁之前不会出现崩溃等问题,否则可能会导致死锁问题。

第三方开源库实现

有很多第三方开源库封装了ZooKeeper,使其更易于使用和集成。以下是一些常用的开源库:

  1. Apache Curator:Curator是一个ZooKeeper客户端库和框架,提供了一组易于使用的抽象,可以帮助处理常见的ZooKeeper使用案例,例如分布式锁和领导者选举。

  2. Spring Cloud Zookeeper:Spring Cloud ZooKeeper是Spring Cloud生态系统中的一部分,提供了使用ZooKeeper进行服务发现和配置管理的支持。它基于Curator客户端库构建,并提供了易于使用的Spring风格API。

  3. Netflix Curator:Netflix Curator是一个基于Apache Curator的库,提供了额外的功能和改进,例如在Curator提供的抽象之上提供更高级别的抽象,更好地支持应用程序的部署和监控,以及更好地处理错误情况。

  4. ZooKeeperClient:ZooKeeperClient是一个简单易用的ZooKeeper客户端库,提供了简单的API和支持异步操作的功能。它还提供了一些用于处理ZooKeeper错误和异常的实用程序。

这些开源库都提供了简化ZooKeeper开发的API和工具,可以大大简化ZooKeeper的使用和集成。

使用 Curator 实现分布式锁的案例

Apache Curator是一个开源的ZooKeeper客户端框架,它提供了一系列的高级API,简化了ZooKeeper的使用。其中之一就是分布式锁的实现。

首先,我们需要添加 Curator 的依赖:

xmlCopy code
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>${curator.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>${curator.version}</version>
</dependency>
javaCopy code
CuratorFramework client = CuratorFrameworkFactory.newClient("zk_address:2181", new ExponentialBackoffRetry(1000, 3));
client.start();
javaCopy code
InterProcessMutex lock = new InterProcessMutex(client, "/distributed-lock");
javaCopy code
lock.acquire();
javaCopy code
if (lock.tryAcquire()) {
    // 获取锁成功
}
javaCopy code
lock.release();
javaCopy code
client.close();
  • 性能受限:由于ZooKeeper是一个集中式的系统,所有的锁请求都需要经过ZooKeeper节点,因此在高并发的情况下,ZooKeeper的性能会成为瓶颈。

  • 依赖性强:使用ZooKeeper实现分布式锁需要依赖ZooKeeper集群,一旦ZooKeeper集群出现问题,可能会导致整个系统的不可用。

但是,使用ZooKeeper实现分布式锁也存在一些问题:

  • 实现简单:只需要基于ZooKeeper提供的API来操作节点即可。

  • 可靠性高:ZooKeeper保证了节点操作的顺序性和原子性,可以有效避免分布式锁的死锁问题。

  • 性能表现优秀:ZooKeeper使用内存存储数据,提供了高速读写的能力,可以支持大量的并发请求。

总的来说,使用ZooKeeper实现分布式锁具有以下优点:

注意事项

总的来说,使用Curator实现分布式锁,相对于直接使用ZooKeeper客户端,更加简单方便,可以大大提高开发效率。

除了InterProcessMutex类外,Curator还提供了其他类型的分布式锁,例如InterProcessSemaphoreMutex、InterProcessReadWriteLock等,可以根据具体的使用场景来选择。

通过以上步骤,就可以使用Apache Curator实现分布式锁。

使用完Curator客户端后,需要将其关闭:

  1. 关闭客户端

注意,在释放锁之前必须先判断是否已经获取到了锁,否则会抛出异常。

使用release()方法释放锁:

  1. 释放锁

另一种方式是使用tryAcquire()方法,该方法会尝试获取锁,如果获取成功则返回true,否则返回false:

获取锁有两种方式,一种是使用acquire()方法,该方法会一直阻塞直到获取到锁:

  1. 获取锁

其中,client是ZooKeeper客户端对象,"/distributed-lock"是锁的路径。

使用Curator提供的InterProcessMutex类来创建分布式锁对象,可以通过以下方式创建:

  1. 创建分布式锁

首先需要创建一个Curator客户端,连接到ZooKeeper集群。可以通过以下方式创建:

  1. 创建Curator客户端

使用Curator实现分布式锁主要有以下几个步骤:

其中,${curator.version} 为 Curator 的版本号,具体版本号可根据实际情况进行指定。

吐血推荐:最近整理之前面试BAT的材料,写了一份《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
领取方法: Java面试BATJ通关手册

 

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

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

相关文章

cmake demo

工程描述 1&#xff0c;为工程添加一个子目录src&#xff0c;用来存储源代码; 2&#xff0c;添加一个子目录doc&#xff0c;用来存储这个工程的文档hello.txt 3&#xff0c;在工程目录添加文本文件COPYRIGHT, README&#xff1b; 4&#xff0c;在工程目录添加一个runhello.sh …

18_FreeRTOS任务通知

目录 任务通知的简介 任务通知值的更新方式 任务通知的优势 任务通知的劣势 任务通知值和通知状态 发送通知相关API函数 接收通知相关API函数 任务通知模拟信号量实验 任务通知模拟消息邮箱实验 任务通知模拟事件标志组实验 任务通知的简介 任务通知:用来通知任务的…

JVM 学习(1)—JVM 与 JMM 内存模型简单理解

一、JVM 内存模型概述 (1) 为什么会出现 JVM 内存模型呢&#xff1f; JVM 内存模型是为规范描述 Java 虚拟机在执行 Java 程序时&#xff0c;将程序中的数据和代码存储到计算机内存中的方式和规则。JVM 内存模型定义 Java 虚拟机所使用的内存结构以及内存区域之间的关系&…

数据归档,存储的完美储备军

数据爆炸性增长的同时&#xff0c;存储成为了大家首要担心的问题大家都希望自家数据保存20年、50年后仍完好无损但是&#xff0c;N年后的数据量已达到一个无法预测的峰值如此大量的数据在保存时极可能存在丢失、损坏等问题这时需要提前对数据进行“备份”、“归档”备份是对数据…

Linux->进程概念于基本创建

1. 进程基本概念 当一个可执行程序被加载到内存当中&#xff0c;并由操作系统将其管理起来&#xff0c;此时这个程序就被称之为进程。也就是下方的&#xff1a; 程序的一个执行实例&#xff0c;正在执行的程序等 担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff…

阿里云云通信风控系统的架构与实践

作者&#xff1a;铭杰 阿里云云通信创立于 2017 年&#xff0c;历经 5 年发展已经孵化出智能消息、智能语音、隐私号、号码百科等多个热门产品。目前&#xff0c;已成为了国内云通信市场的领头羊&#xff0c;在国际市场上服务范围也覆盖了 200 多个国家。随着业务的不断壮大&am…

正则表达式是如何运作的?

在日常的开发工作当中&#xff0c;我们必不可免的会碰到需要使用正则的情况。 正则在很多时候通过不同的组合方式最后都可以达到既定的目标结果。比如我们有一个需要匹配的字符串&#xff1a; hello&#xff0c;我们可以通过 / .</p>/ 以及 / .?</p>/ 来匹配&…

数据分析与SAS学习笔记8

过程步&#xff1a;一个典型的SAS完整程序&#xff1a; 代码说明&#xff1a; 1&#xff09;reg&#xff1a;回归分析&#xff1b; 2&#xff09;model&#xff1a;因变量和自变量。 proc开头部分叫过程步。 常用过程&#xff1a; SORT过程&#xff1a; PRINT过程与FORTMAT…

Linux环境下绕过长度限制写入webshell

前提当命令执行漏洞对长度有限制时&#xff0c;我们可以通过一些Linux命令生成文件进行执行。如果应用程序是使用shell解析器来执行命令或文件&#xff0c;那么不需要该文件具有执行属性(x)如果应用程序没有shell解析器&#xff0c;那么写入文件内容时&#xff0c;可以第一条语…

终极方案,清理 docker 占用磁盘过大问题, 亲测有效!

背景 在笔者的工作测试环境中&#xff0c;使用过程中突然出现根磁盘快吃满了&#xff08;docker也是使用的根池盘的/var/lib/docker&#xff09;&#xff0c; wtf &#xff1f; 服务用不了&#xff1f; 当然网上找到了一些常规的清楚docker 日志文件 但是通过df -hT 查看到over…

2023年Java面试题精选(蚂蚁金服/滴滴/美团/拼多多腾讯)

作为一名优秀的程序员&#xff0c;技术面试都是不可避免的一个环节&#xff0c;一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 如果你参加过一些大厂面试&#xff0c;肯定会遇到一些这样的问题&#xff1a; 1、看你项目都用的框架&#xff0c;熟悉…

Linux 中使用 docker-compose 部署 MongoDB 6 以上版本副本集及配置 SSL / TLS 协议

一、准备环境 MongoDB 副本集部署至少 3 个节点&#xff08;奇数节点&#xff09;&#xff0c;为了保障数据安全性&#xff0c;可考虑将 MongoDB 节点分布在不同的主机上&#xff0c;本示例使用一台主机部署 3 个 MongoDB示例。 1、创建 MongoDB 集群数据相关目录 # 创建 Mo…

大数据|大数据基础(概念向)

目录 &#x1f4da;大数据概念 &#x1f407;常见数据存储单位 &#x1f407;大数据的特点&#xff08;5V&#xff09; &#x1f407;大数据 VS 数据库 &#x1f31f;数据库 &#x1f31f;大数据 &#x1f4da;大数据业务分析基本步骤 &#x1f407;收集数据 &#x1f4…

RockerMQ简介和单节点部署

目录一、RockerMQ简介二、Linux中单节点部署1、准备工作2、下载和解压3、修改初始内存4、启动5、查看进程6、发送接收消息测试7、关闭三、控制台的安装与启动(可视化页面)1、修改配置&#xff08;1&#xff09;修改端口号&#xff08;2&#xff09;指定RocketMQ的name server地…

企业知识管理常见的误区及解决方案

在企业信息化的背景下&#xff0c;越来越多的首席信息官&#xff08;CIO&#xff09;承担着促进组织知识管理实施的责任。然而&#xff0c;从实践的角度来看&#xff0c;虽然我国大多数知识管理实施项目都取得了一定的成果&#xff0c;但与预期有很大的不同&#xff0c;甚至许多…

这18个被全网吹爆了的AI绘画工具,分享给你!

伴随着ChatGPT的横空出世&#xff0c;一场史无前例的科技革命正在拉开序幕。 AI 拥有强大的信息储备和数据处理能力&#xff0c;无论是速度、质量&#xff0c;还是思维模式&#xff0c;都让人只呼不得了&#xff01;写代码、造论文丝毫不在话下&#xff0c;甚至还能和你探讨茶…

当 Amazon Lambda 遇上 Apache APISIX 可以擦出什么火花?

本文首先介绍了什么是 Serverless&#xff0c;以及为什么需要 Serverless&#xff1b;其次&#xff0c;讲述了一个好的网关在 Serverless 架构下的重要性&#xff0c;而 APISIX 就是这样的一个网关&#xff1b;最后&#xff0c;本文重点介绍了 APISIX 中的 Serverless 类型的插…

您应该知道的几个安卓照片恢复应用程序

如果您不小心删除了存储在 Android 手机上的一些重要照片&#xff0c;该怎么办&#xff1f;如果您之前已创建备份&#xff0c;则只需将备份文件中的照片恢复到您的手机即可。但数据丢失往往是突然发生的&#xff0c;可能是由于误操作、恢复出厂设置或物理损坏等原因造成的。如果…

高性能低功耗4口高速USB2.0 HUB NS1.1S 兼容FE1.1

NS1.1S是一款高性能、低功耗4口高速 USB2.0 HUB 控制器&#xff0c;上行端口兼容高速 480MHz和全速12MHz两种模式&#xff0c;4个下行端口兼容高速480MHz、全速12MHz、低速1.5MHz三种模式。 NS1.1S采用状态机单事务处理架构&#xff0c;而非单片机架构&#xff0c;多个事务缓冲…

Java无法通过形参设置为null改变实参

文章目录问题描述问题例子问题分析问题描述 在实际业务开发过程中&#xff0c;我们会把实参传递给形参&#xff0c;在方法体内对引用对象进行构建或者修改&#xff0c;从而改变实参&#xff0c;因为对形参对象属性修改时&#xff0c;实参对象也会随着改变&#xff0c;详情请看&…