Spring Boot 中的 Zookeeper 分布式锁

news/2024/4/26 20:37:42/文章来源:https://blog.csdn.net/2302_77835532/article/details/131529641

Spring Boot 中的 Zookeeper 分布式锁

分布式锁是分布式系统中常用的一个同步工具,它可以在多个进程之间协调访问共享资源,避免数据不一致或重复处理。在分布式环境中,由于网络通信的延迟和节点故障等原因,传统的锁机制无法满足需求。因此,分布式锁成为了实现分布式同步的常用方案之一。

Zookeeper 是一个分布式协调服务,它提供了高可用、高性能、可扩展的分布式锁机制。Spring Boot 是一个基于 Spring 框架的开发框架,它提供了对 Zookeeper 分布式锁的集成支持。本文将介绍 Spring Boot 中的 Zookeeper 分布式锁的原理和使用方法。

在这里插入图片描述

原理

Zookeeper 分布式锁的原理是基于 Zookeeper 的节点同步机制。在 Zookeeper 中,每个节点都有一个版本号,节点的状态变化都会被记录下来。当一个进程想要获取锁时,它会在 Zookeeper 中创建一个临时节点,并尝试获取锁。如果创建节点成功,则说明获取锁成功;否则,进程需要等待直到锁被释放。

Zookeeper 分布式锁的实现需要考虑以下几个问题:

  1. 如何保证锁的互斥性:只有一个进程可以获取锁,其他进程需要等待。
  2. 如何保证锁的可重入性:同一个进程可以重复获取锁而不会死锁。
  3. 如何避免锁的永久等待:如果一个进程获取锁后崩溃了,如何保证锁能够被释放。

为了解决这些问题,Zookeeper 分布式锁采用了以下机制:

  1. 利用 Zookeeper 节点的互斥性:每个节点在同一时刻只能被一个进程创建。
  2. 利用 Zookeeper 节点的临时性:当一个进程崩溃或断开连接时,它创建的节点会被自动删除。
  3. 利用 Zookeeper 节点的顺序性:Zookeeper 中的节点有序排列,每个节点都有一个唯一的编号。进程获取锁时,会创建一个带有序号的节点,然后判断自己是否是最小的节点。如果是最小的节点,则获取锁成功;否则,进程需要等待。

使用方法

Spring Boot 对 Zookeeper 分布式锁的支持是通过 spring-integration-zookeeper 模块实现的。下面是一个简单的示例,演示了如何在 Spring Boot 中使用 Zookeeper 分布式锁。

首先,我们需要在 pom.xml 中添加以下依赖:

<dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-zookeeper</artifactId><version>5.5.0</version>
</dependency>

然后,我们可以在 Spring Boot 中使用 ZookeeperLockRegistry 类来创建一个分布式锁。下面是一个使用 ZookeeperLockRegistry 类的示例:

@Configuration
public class ZookeeperLockConfiguration {@Beanpublic ZookeeperLockRegistry zookeeperLockRegistry(CuratorFramework curatorFramework) {return new ZookeeperLockRegistry(curatorFramework, "/locks");}@Beanpublic CuratorFramework curatorFramework() throws Exception {return CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryUntilElapsed(1000, 4));}}

在上面的示例中,我们创建了一个名为 zookeeperLockRegistry 的 Bean,用于管理分布式锁。我们还创建了一个名为 curatorFramework 的 Bean,用于创建 Zookeeper 客户端。

现在,我们可以在需要使用分布式锁的地方使用 ZookeeperLockRegistry 类来创建一个锁对象,并调用 lock() 方法获取锁。下面是一个示例:

@Autowired
private ZookeeperLockRegistry zookeeperLockRegistry;public void doSomething() {Lock lock = zookeeperLockRegistry.obtain("my-lock");if (lock.tryLock()) {try {// TODO: 执行业务逻辑} finally {lock.unlock();}} else {// TODO: 获取锁失败的处理逻辑}
}

在上面的示例中,我们首先通过 zookeeperLockRegistry.obtain("my-lock") 方法获取了一个名为 my-lock 的锁对象。然后,我们调用 tryLock() 方法尝试获取锁。如果获取锁成功,我们就可以执行业务逻辑了;否则,我们需要处理获取锁失败的情况。

需要注意的是,在使用分布式锁的时候,我们需要遵循以下几个原则:

  1. 锁的范围应该尽可能小:锁的范围越小,锁的互斥性就越弱,系统的吞吐量就越高。
  2. 锁的超时时间应该合理设置:如果锁的持有者崩溃了或者网络出现了问题,其他进程需要等待一段时间之后才能获取锁,这个时间应该设置得不太长也不太短。
  3. 锁的释放应该在 finally 块中进行:无论业务逻辑是否出现异常,都应该保证锁能够被释放。

代码示例

下面是一个完整的 Spring Boot 项目,演示了如何使用 Zookeeper 分布式锁。在这个项目中,我们模拟了一个简单的计数器,多个进程可以同时对计数器进行加一操作,但是只有一个进程能够成功获取锁并进行操作,其他进程需要等待。

@SpringBootApplication
public class ZookeeperLockDemoApplication {public static void main(String[] args) {SpringApplication.run(ZookeeperLockDemoApplication.class, args);}@Beanpublic ZookeeperLockRegistry zookeeperLockRegistry(CuratorFramework curatorFramework) {return new ZookeeperLockRegistry(curatorFramework, "/locks");}@Beanpublic CuratorFramework curatorFramework() throws Exception {return CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryUntilElapsed(1000, 4));}}
@RestController
public class CounterController {private AtomicInteger counter = new AtomicInteger(0);@Autowiredprivate ZookeeperLockRegistry zookeeperLockRegistry;@GetMapping("/counter")public int getCounter() {return counter.get();}@PostMapping("/counter")public int increaseCounter() {Lock lock = zookeeperLockRegistry.obtain("/counter-lock");try {if (lock.tryLock(10, TimeUnit.SECONDS)) {try {counter.incrementAndGet();} finally {lock.unlock();}} else {throw new RuntimeException("Failed to acquire lock for counter!");}} catch (InterruptedException e) {throw new RuntimeException("Failed to acquire lock for counter!", e);}return counter.get();}}

在上面的代码中,我们创建了一个名为 CounterController 的 RESTful 接口,提供了对计数器的读写操作。在写操作中,我们使用 zookeeperLockRegistry.obtain("/counter-lock") 方法获取了一个名为 /counter-lock 的锁对象,并调用 tryLock(10, TimeUnit.SECONDS) 方法尝试获取锁,超时时间为 10 秒。如果获取锁成功,我们就可以对计数器进行加一操作了;否则,我们抛出一个运行时异常。

结论

Zookeeper 分布式锁是实现分布式同步的常用方案之一,它基于 Zookeeper 的节点同步机制实现了一个高可用、高性能、可扩展的分布式锁机制。在 Spring Boot 中,我们可以通过 spring-integration-zookeeper 模块来集成 Zookeeper 分布式锁的支持,使用起来非常方便。

在使用 Zookeeper 分布式锁的时候,我们需要遵循一些原则,比如锁的范围应该尽可能小,锁的超时时间应该合理设置,锁的释放应该在 finally 块中进行等等。另外,需要注意的是,分布式锁虽然可以解决分布式同步的问题,

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

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

相关文章

JavaScript多功能甘特图组件 - jsGantt

jsGantt 是一个可定制的、灵活的、多语言的甘特图组件&#xff0c;由原生 JavaScript 构建。它使用客户端渲染以获得快速的性能和动态的交互性。非常适用于任何需要交互式时间线或时间表显示的项目。 更多特点 多语言支持&#xff1a; 通过对多语言的支持&#xff0c;使您的甘…

nginx配置https加密

以下操作版本为Ubuntu2004&#xff0c;文件位置可能略有不同 https 功能 Web网站的登录页面通常都会使用https加密传输的&#xff0c;加密数据以保障数据的安全&#xff0c;HTTPS能够加密信息&#xff0c;以免敏感信息被第三方获取&#xff0c;所以很多银行网站或电子邮箱等等…

fiddler弱网测试 和 Chrome浏览器弱网设置

文章目录 前言 一、fiddler弱网测试 二、Chrome浏览器弱网测试 步骤1&#xff1a;在Fiddler中启动弱网 步骤2&#xff1a;设置网络参数 步骤3&#xff1a;设置完成后&#xff0c;保存 三、弱网测试关注点 总结 前言 测试APP、web经常需要用到弱网测试&#xff0c;也就是…

Flink运行原理

Apache Flink是什么&#xff1f;对于这个问题&#xff0c;Apache软件基金会官方给出了定义&#xff1a;Flink是一种框架和分布式处理引擎&#xff0c;主要用于对无界和有界数据流进行有状态计算。 本文将从以下几个方面来了解flink运行原理&#xff1a; 【Flink运行时四大组件…

Vault AppRole最佳实现过程

AppRole AppRole身份验证方法允许机器或应用程序使用 Vault 定义的角色进行身份验证。AppRole 的开放式设计支持使用不同的工作流和配置来应对大量应用程序。这种身份验证方法主要是面向自动化工作流程(机器和服务)设计的,对人类操作者不太有用。 “AppRole”代表一组 Vau…

clickhouse日志表占用大量磁盘空间

clickhouse日志表占用大量磁盘空间 sql&#xff1a; SELECT sum(rows) AS 总行数, formatReadableSize(sum(data_uncompressed_bytes)) AS 原始大小, formatReadableSize(sum(data_compressed_bytes)) AS 压缩大小, round((sum(data_compressed_bytes) / sum(data_uncompresse…

linux 操作系统内核态用户态

1. 32位系统一个进程最多有多少堆内存 对 32 位操作系统而言&#xff0c;它的寻址空间是4G&#xff08;2的32次方&#xff09;&#xff0c;Linux把它分为两部分&#xff1a;最高的1G(虚拟地址从0xC0000000到0xffffffff)用做内核本身&#xff0c;成为“内核空间”&#xff0c;而…

【全文搜索选型】全文搜索 PostgreSQL 或 ElasticSearch

在本文中&#xff0c;我记录了在 PostgreSQL&#xff08;使用 Django ORM&#xff09;和 ElasticSearch 中实现全文搜索 (FTS) 时的一些发现。 作为一名 Django 开发人员&#xff0c;我开始寻找可用的选项来在大约一百万行的标准大小上执行全文搜索。有两个值得尝试的选项&…

新发布的 DBeaver 23.1.1 版本正式支持时序数据库 TDengine

众所周知&#xff0c;DBeaver 是一个流行的开源数据库管理和 SQL 客户端工具&#xff0c;为管理和使用各种类型的数据库&#xff08;包括多个时序数据库&#xff09;提供强大而灵活的平台。为了让大家在应用上更加便捷&#xff0c;我们与 DBeaver 达成合作&#xff0c;新发布的…

【ARM】-IRQ 和 FIQ 异常中断处理程序的返回

文章目录 处理流程示例代码实现 处理流程 通常处理器执行完当前指令后&#xff0c;查询 IRQ 中断引脚及 FIQ 中断引脚&#xff0c;并且查看系统是否允许 IRQ 中断及 FIQ中断。 如果有中断引脚有效&#xff0c;并且系统允许该中断产生&#xff0c;处理器将产生 IRQ 异常中断或 …

【直播预告】HarmonyOS极客松赋能直播第四期:HarmonyOS开发经验分享

直播预约通道&#xff1a;【直播预告】HarmonyOS极客松赋能直播第四期&#xff1a;HarmonyOS开发经验分享

为什么从 MVC 到 DDD,架构的本质是什么?

作者&#xff1a;小傅哥 博客&#xff1a;https://bugstack.cn 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 本文来自于小傅哥新编写的 《Java简明教程》 系列内容&#xff0c;本教程意在于通过简单、明了、清晰的成体系内容&#xff0c;教…

IP 扫描程序:轻松发现、扫描和跟踪 IP 空间

什么是 IP 扫描 IP 扫描是实时持续监控网络 IP 地址空间的过程。包括 ICMP ping 扫描和 SNMP 扫描在内的网络协议数量用于扫描网络中的 IP 地址。网络管理员依靠 IP 扫描程序轻松检查和管理 IP 地址空间。使用网络 IP 扫描程序进行 IP 扫描可查看 IP 地址空间利用率和性能。 …

网络io模型、同步异步及libuv

网络io模型及基础概念 概念说明 用户空间与内核空间 操作系统的核心是内核&#xff0c;独立于普通的应用程序&#xff0c;可以访问受保护的内存空间&#xff0c;也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核&#xff08;kernel&#xff09;&#xff0…

Unity3D:工具栏

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 工具栏 在 Unity Editor 顶部可以看到工具栏。 工具栏不是窗口&#xff0c;是 Unity 界面中唯一无法重新排列的部分。 有关场景视图中的其他工具&#xff0c;请参阅叠加。 工具栏…

微服务:Springboot集成Hystrix实现熔断、降级、隔离

文章目录 前言知识积累Springboot集成Hystrix1、maven依赖引入2、application开启feign的hystrix支持&#xff08;客户端配置限流降级熔断&#xff09;3、入口类增加EnableFeignClients EnableHystrix 开启feign与hystrix4、feign调用增加降级方法服务端配置限流降级熔断(选择使…

中移物联车联网项目,在 TDengine 3.0 的应用

小T导读&#xff1a;在中移物联网的智慧出行场景中&#xff0c;需要存储车联网设备的轨迹点&#xff0c;还要支持对车辆轨迹进行查询。为了更好地进行数据处理&#xff0c;他们在 2021 年上线了 TDengine 2.0 版本的 5 节点 3 副本集群。 3.0 发布后&#xff0c;它的众多特性吸…

关于visual studio 2010 及以上版本 引入boost库的最新解决方法

之前没有怎么用到boost库&#xff0c;出来实习需要去编译一些代码&#xff0c;需要引入boost第三方库&#xff0c;在这过程中&#xff0c;一直出现 LINK : fatal error LNK1104: 无法打开文件“libboost_filesystem-vc100-mt-gd-x3 错误&#xff0c; 但是也确实是跟其他教程学过…

myCobot机器人ChatGPT应用:设计原则和模型能力

我们将 ChatGPT 的功能扩展到机器人&#xff0c;并通过语言直观地控制机器人手臂、无人机和家庭助理机器人等多个平台。 你有没有想过用你自己的话告诉机器人该怎么做&#xff0c;就像你对人类一样&#xff1f;只是告诉你的家庭助理机器人&#xff1a;“请加热我的午餐”&…

MYSQL根据标签查询数据

场景条件&#xff1a; 1.根据用户id查询到该id绑定的标签&#xff08;可能是多个标签也可能是单个标签&#xff09; 2.根据标签的id查询到绑定标签id的信息表 SELECT labelID FROM LRrelation WHERE relationID 1 SELECT * FROM notification SELECT * FROM notification…