分布式锁的实现:Redis和Zookeeper

在分布式系统中,确保数据的一致性和避免并发问题是非常重要的。分布式锁是解决这些问题的关键技术之一。本文将详细介绍如何使用Redis和Zookeeper实现分布式锁,并通过Java代码示例帮助读者理解其实现原理。

1. 分布式锁的基本概念

分布式锁是一种用于协调多个节点对共享资源访问的机制。它确保在任何时刻,只有一个节点能够持有锁并访问资源,从而避免并发冲突。

2. 使用Redis实现分布式锁

Redis是一个高性能的键值存储系统,非常适合用于实现分布式锁。下面是一个使用Redis实现分布式锁的Java示例。

2.1 依赖引入

首先,需要在项目中引入Redis客户端库,例如Jedis。

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>
2.2 分布式锁实现
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;public class RedisDistributedLock {private static final String LOCK_KEY = "distributed_lock";private static final String LOCK_VALUE = "locked";private static final int EXPIRE_TIME = 10; // 锁的过期时间,单位秒private Jedis jedis;public RedisDistributedLock(Jedis jedis) {this.jedis = jedis;}public boolean acquireLock() {SetParams params = SetParams.setParams().nx().ex(EXPIRE_TIME);String result = jedis.set(LOCK_KEY, LOCK_VALUE, params);return "OK".equals(result);}public void releaseLock() {jedis.del(LOCK_KEY);}
}
2.3 使用示例
public class RedisLockDemo {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");RedisDistributedLock lock = new RedisDistributedLock(jedis);try {if (lock.acquireLock()) {System.out.println("Lock acquired, performing critical section operations...");// 执行关键操作} else {System.out.println("Failed to acquire lock.");}} finally {lock.releaseLock();jedis.close();}}
}
3. 使用Zookeeper实现分布式锁

Zookeeper是一个分布式协调服务,也可以用于实现分布式锁。下面是一个使用Zookeeper实现分布式锁的Java示例。

3.1 依赖引入

首先,需要在项目中引入Zookeeper客户端库。

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.7.0</version>
</dependency>
3.2 分布式锁实现
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class ZookeeperDistributedLock {private static final String LOCK_ROOT = "/locks";private static final String LOCK_NODE = LOCK_ROOT + "/lock_";private ZooKeeper zk;private String lockPath;public ZookeeperDistributedLock(String connectString) throws IOException, InterruptedException {CountDownLatch connectedSignal = new CountDownLatch(1);zk = new ZooKeeper(connectString, 5000, new Watcher() {@Overridepublic void process(WatchedEvent event) {if (event.getState() == Event.KeeperState.SyncConnected) {connectedSignal.countDown();}}});connectedSignal.await();}public boolean acquireLock() throws KeeperException, InterruptedException {lockPath = zk.create(LOCK_NODE, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);while (true) {List<String> children = zk.getChildren(LOCK_ROOT, false);Collections.sort(children);if (lockPath.endsWith(children.get(0))) {return true;} else {int index = Collections.binarySearch(children, lockPath.substring(LOCK_ROOT.length() + 1));String previousLockPath = LOCK_ROOT + "/" + children.get(index - 1);final CountDownLatch latch = new CountDownLatch(1);zk.exists(previousLockPath, new Watcher() {@Overridepublic void process(WatchedEvent event) {if (event.getType() == Event.EventType.NodeDeleted) {latch.countDown();}}});latch.await();}}}public void releaseLock() throws KeeperException, InterruptedException {if (lockPath != null) {zk.delete(lockPath, -1);lockPath = null;}}public void close() throws InterruptedException {zk.close();}
}
3.3 使用示例
public class ZookeeperLockDemo {public static void main(String[] args) {try {ZookeeperDistributedLock lock = new ZookeeperDistributedLock("localhost:2181");try {if (lock.acquireLock()) {System.out.println("Lock acquired, performing critical section operations...");// 执行关键操作} else {System.out.println("Failed to acquire lock.");}} finally {lock.releaseLock();lock.close();}} catch (Exception e) {e.printStackTrace();}}
}
4. 结论

通过上述示例,我们展示了如何使用Redis和Zookeeper实现分布式锁。这两种方法各有优劣,选择哪种方法取决于具体的应用场景和需求。

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

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

相关文章

乐鑫AWS IoT ExpressLink方案,简化物联网设备连接AWS IoT服务

在现代科技迅速发展的今天&#xff0c;物联网&#xff08;IoT&#xff09;已经成为连接物理世界与数字世界的重要桥梁&#xff0c;越来越多的设备开始接入网络&#xff0c;实现智能化控制。 在这个大背景下&#xff0c;乐鑫携手亚马逊&#xff0c;推出了AWS IoT ExpressLink方…

Linux:Linux发展史

大家好&#xff01;此篇文章并非技术博文&#xff0c;而是简单了解Linux的时代背景和发展史&#xff0c;只有知其所以然才能让我们更好地让走进Liunx的世界&#xff01; 一、计算机的发展历史背景 首先我们要知道&#xff0c;早期大多数科技的进步都是以国家的对抗为历史背景的…

Java语言程序设计基础篇_编程练习题**15.17 (几何问题:寻找边界矩形)

**15.17 (几何问題:寻找边界矩形) 请编写一个程序&#xff0c;让用户可以在一个二维面板上动态地增加和移除点&#xff0c;如图15-29a所示。当点加入和移除的时候&#xff0c;一个最小的边界矩形更新显示。假设每个点的半径是 10 像素 解题思路&#xff1a; 这道题可以从编程…

数学建模(4)——支持向量机算法

一、代码示例 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC from sklearn.metrics import clas…

1-如何挑选Android编译服务器

前几天&#xff0c;我在我的星球发了一条动态&#xff1a;入手洋垃圾、重操老本行。没错&#xff0c;利用业余时间&#xff0c;我又重新捣鼓捣鼓代码了。在接下来一段时间&#xff0c;我会分享我从服务器的搭建到完成Android产品开发的整个过程。这些东西之前都是折腾过的&…

JVM类加载机制详解

Java在运行期才对类进行加载到内存、连接、初始化过程。这使得Java应用具有极高的灵活性和拓展性&#xff0c;可以依赖运行期进行动态加载和动态连接。 主要加载哪些&#xff1f;Java中的数据类型分为基本数据类型和引用数据类型&#xff0c;基本数据类型由虚拟机预先定义&…

Flask: URL 视图函数 路由

Flask: URL 视图函数 路由 from flask import Flask, request app Flask(__name__) # URL: / # 视图函数: hello_world # 路由: 将根URL映射到hello_world函数 app.route(/) def hello_world(): return Hello, World! # URL: /user/<int:user_id> # 视图…

站在资本投资领域如何看待分布式光纤传感行业?

近年来&#xff0c;资本投资领域对于分布式光纤传感行业并不十分敏感。这主要是由于分布式光纤传感技术是一个专业且小众的领域&#xff0c;其生命周期相对较长&#xff0c;缺乏爆发性&#xff0c;与消费品或商业模式创新产业有所不同。此外&#xff0c;国内的投资环境也是影响…

双向长短期记忆网络(BiLSTM)及其Python和MATLAB实现

长短期记忆网络&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;&#xff0c;旨在克服传统RNN在长序列数据中的梯度消失和梯度爆炸问题&#xff0c;并能更有效地捕捉长期依赖关系。除了基本的LSTM结构外&a…

谷粒商城实战笔记-42-前端基础-Vue-生命周期和钩子函数

下面是Vue官网关于生命周期及不同阶段的钩子函数的图示。 Vue 实例生命周期是指从一个组件被创建到最终被销毁的整个过程。 在这一过程中&#xff0c;Vue 提供了一系列的“钩子”函数&#xff0c;在生命周期的不同阶段执行自定义的代码。 以下是 Vue 对象生命周期的主要阶段…

Ubuntu 20.04搭建OpenCV 4.5.0 C++环境

Ubuntu 20.04搭建OpenCV 4.5.0 & C环境_ubuntu opencv4.5.0-CSDN博客

图片转换之heic转jpg(使用ImageMagick)

缘由&#xff1a;iphone的图库&#xff0c;用jpg拍照保存后内存占比较大&#xff0c;heic格式会微缩不少。问题来了&#xff0c;电脑不能直接小图预览heic。 分析&#xff1a;现在就是解决小图预览的问题&#xff08;大图用wps可以看&#xff09; 解决&#xff1a;查找了一些…

Vue中的diff算法

文章目录 diff算法是什么比较方式源码分析patchpatchVnodeupdateChildren小结Vue3中diff算法优化diff算法是什么 diff算法是一种通过同层的树节点进行比较的高效算法 其有两个特点: 比较只会在同层级进行,不会跨层级比较在dff比较的过程中,循环从两边向中间比较(首位交叉…

基于神经网络的聚类分析

神经网络是一种非常有用的机器学习模型&#xff0c;具有无数的应用。今天&#xff0c;我们将分析一个数据集&#xff0c;看看我们是否可以通过应用无监督聚类技术来查找数据中的模式和隐藏分组&#xff0c;从而获得新的见解。 我们的目标是对复杂数据进行降维&#xff0c;以便…

基于深度学习的草莓成熟度实时检测系统(UI界面+YOLOv8/v7/v6/v5模型+完整代码与数据集)

1. 引言 在农业领域&#xff0c;草莓的成熟度检测是保证果实品质的重要环节。传统的方法依赖于人工经验&#xff0c;不仅耗时费力&#xff0c;还容易出错。本文介绍如何使用YOLO&#xff08;You Only Look Once&#xff09;系列模型&#xff08;YOLOv8/v7/v6/v5&#xff09;构…

mysql面试(一)

前言 从今天开始&#xff0c;更新一些mysql的基础知识&#xff0c;面试会遇到的知识点之类的内容。比如四个隔离级别&#xff0c;mvcc机制&#xff0c;三大日志&#xff0c;索引&#xff0c;B树的形成等等&#xff0c;从数据库的底层来剖析索引和树是怎么形成的&#xff0c;以…

接口自动化测试框架实战-0-项目功能概览

熟悉我CSDN的朋友们应该知道&#xff0c;之前已经更新了requests、pytest、allure2、yaml、jenkins、postman等基础知识的合集。相信大家对接口测试已经有了全面的认识&#xff0c;现在应该迫不及待地想要一个实战项目了。接下来的文章中&#xff0c;我们将把这些知识点串联起来…

C++学习笔记02-结构基础(问题-解答自查版)

前言 以下问题以Q&A形式记录&#xff0c;基本上都是笔者在初学一轮后&#xff0c;掌握不牢或者频繁忘记的点 Q&A的形式有助于学习过程中时刻关注自己的输入与输出关系&#xff0c;也适合做查漏补缺和复盘。 本文对读者可以用作自查&#xff0c;答案在后面&#xff0…

wxs 和小程序的Page能不能在执行过程中传值?wxs能不能往page里面传值?

wxs 和小程序的 Page 可以在执行过程中传值。wxs 可以接收来自 Wxml 的数据,也可以将数据传递回 Wxml。这种数据传递是单向的,从 Wxml 到 wxs。 下面是一个例子,展示了如何在 wxs 和 Page 之间传值: {{utils.processInput(inputValue)}} function processInput(value) { if (!…

【Linux】HTTP 协议

目录 1. URL2. HTTP 协议2.1. HTTP 请求2.2. HTTP 响应 1. URL URL 表示着是统一资源定位符(Uniform Resource Locator), 就是 web 地址&#xff0c;俗称“网址”; 每个有效的 URL 可以通过互联网访问唯一的资源, 是互联网上标准资源的地址; URL 的主要由四个部分组成: sche…