分布式中间件:基于 Redis 实现分布式锁

分布式中间件:基于 Redis 实现分布式锁

一、背景引入

在当今的互联网应用中,分布式系统变得越来越常见。在分布式环境下,多个服务实例可能会同时对共享资源进行读写操作,这就很容易引发数据不一致等问题。比如电商系统中的库存扣减,如果多个订单处理服务同时对同一商品的库存进行操作,就可能导致超卖现象。为了解决这类问题,分布式锁应运而生。分布式锁能够保证在分布式系统中,同一时刻只有一个服务实例可以对共享资源进行操作,从而确保数据的一致性和完整性。

Redis 作为一款高性能的开源内存数据库,具有丰富的数据结构和原子操作特性,成为了实现分布式锁的理想选择。接下来,我们将深入探讨如何基于 Redis 实现分布式锁。

二、Redis 实现分布式锁的原理

(一)基本原理

Redis 实现分布式锁主要是利用了其原子性操作。Redis 提供了 SET 命令,该命令可以原子性地设置一个键值对,并且可以同时设置过期时间。当多个客户端同时尝试获取锁时,只有一个客户端能够成功设置该键值对,从而获得锁。

(二)具体命令

使用 SET key value NX PX timeout 命令,其中:

  • key:表示锁的名称,通常是一个具有业务含义的字符串,例如 product:1:lock 表示对商品 ID 为 1 的资源加锁。
  • value:可以是一个唯一的标识,用于区分不同的客户端,防止误解锁。例如,可以使用 UUID 作为 value。
  • NX:表示只有当键不存在时才进行设置操作,如果键已经存在,则设置失败,这保证了同一时刻只有一个客户端能获得锁。
  • PX timeout:设置键的过期时间,单位为毫秒。这是为了防止持有锁的客户端出现异常(如崩溃)而导致锁无法释放,造成死锁。

三、代码实现

(一)Java 代码示例

import redis.clients.jedis.Jedis;
import java.util.UUID;public class RedisDistributedLock {private static final String LOCK_KEY = "my_distributed_lock";private static final int LOCK_EXPIRE_TIME = 5000; // 锁的过期时间,单位:毫秒private Jedis jedis;public RedisDistributedLock() {this.jedis = new Jedis("localhost", 6379);}public String acquireLock() {String requestId = UUID.randomUUID().toString();String result = jedis.set(LOCK_KEY, requestId, "NX", "PX", LOCK_EXPIRE_TIME);if ("OK".equals(result)) {return requestId;}return null;}public boolean releaseLock(String requestId) {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";Object result = jedis.eval(script, 1, LOCK_KEY, requestId);return "1".equals(result.toString());}public void close() {jedis.close();}
}

(二)代码解释

  • acquireLock 方法:生成一个唯一的 requestId,然后使用 SET 命令尝试获取锁。如果返回 OK,表示成功获取锁,返回该 requestId;否则返回 null
  • releaseLock 方法:使用 Lua 脚本确保释放锁的操作是原子性的。首先检查当前锁的 value 是否与传入的 requestId 相等,如果相等则删除该键,释放锁,并返回 1;否则返回 0。
  • close 方法:关闭 Redis 连接。

(三)使用示例

public class Main {public static void main(String[] args) {RedisDistributedLock lock = new RedisDistributedLock();String requestId = lock.acquireLock();if (requestId != null) {try {System.out.println("成功获取锁,开始执行临界区代码");// 模拟临界区代码执行Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.releaseLock(requestId);System.out.println("成功释放锁");}} else {System.out.println("获取锁失败");}lock.close();}
}

四、Redis 分布式锁的优缺点

(一)优点

  1. 高性能:Redis 是基于内存的数据库,读写速度非常快,能够满足高并发场景下的锁操作需求。
  2. 原子操作:Redis 提供了原子操作,如 SET 命令和 Lua 脚本,保证了锁的获取和释放操作的原子性,避免了并发问题。
  3. 可扩展性:Redis 可以通过集群或主从复制等方式实现高可用性和可扩展性,满足大规模分布式系统的需求。

(二)缺点

  1. 单点故障:如果 Redis 节点出现故障,可能会导致锁服务不可用。虽然可以通过集群或主从复制来解决,但仍然存在一定的风险。
  2. 时钟漂移:Redis 的锁超时机制依赖于系统时钟,如果不同节点的时钟存在漂移,可能会导致锁提前或延迟释放。
  3. 锁释放问题:如果客户端在持有锁期间崩溃,锁可能无法正常释放,需要依赖锁超时机制来解决。

五、应用场景

  1. 分布式系统中的数据一致性:在多个服务同时访问和修改共享数据时,使用分布式锁可以保证数据的一致性。例如,多个订单处理服务对同一商品的库存进行操作时,使用分布式锁可以避免超卖现象。
  2. 任务调度:在分布式任务调度系统中,使用分布式锁可以保证同一个任务在同一时间只被一个节点执行。例如,定时清理缓存的任务,避免多个节点同时执行导致数据不一致。
  3. 资源限流:在多个客户端同时访问有限资源时,使用分布式锁可以限制同一时间的访问数量。例如,限制同一时间对某个接口的并发访问数量。

六、总结

基于 Redis 实现分布式锁是一种简单、高效的解决方案,能够满足大多数分布式系统的需求。通过合理设置锁的过期时间和使用原子操作,可以保证锁的正确性和可靠性。但同时也需要注意 Redis 的单点故障、时钟漂移等问题,在实际应用中需要根据具体场景进行优化和改进。希望本文能帮助你更好地理解和应用基于 Redis 的分布式锁。

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

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

相关文章

尝试使用Tauri2+Django+React项目(2)

前言 尝试使用tauri2DjangoReact的项目-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146403103在前面笔者不知道怎么做,搞了半天 笔者看到官网,原来可以使用二进制文件,好好好 嵌入外部二进制文件 | Taurihttps://v2.taur…

【006安卓开发方案调研】之大厂APP混合开发方案

基于国内大厂在安卓混合开发领域的实践,以下是主流解决方案及其核心技术实现路径的深度解析: 一、主流混合开发解决方案分类 1. Flutter混合开发体系 架构设计 采用组件化分层架构,原生工程作为宿主,通过MethodChannel与Flutter…

Mysql配套测试之查询篇

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 条件查询简单测试&#xff1a; 1.查询英语成绩不及格的同学(<60) 2…

设计和布局硬件电路是嵌入式系统开发的重要环节

设计和布局硬件电路是嵌入式系统开发的重要环节&#xff0c;涉及从需求分析到原理图设计、PCB&#xff08;印刷电路板&#xff09;布局以及最终的硬件调试。以下是完整的流程和技术要点&#xff1a; 1. 硬件电路设计的基本流程 1.1 需求分析 明确功能需求&#xff1a;确定系统…

PicFlow:一个图片处理与上传工作流工具(图床上传工具)

自从学习搭建网站以来&#xff0c;我就把很多图片托管在七牛云等图床平台上。以前总是通过网页批量上传&#xff0c;需要登录并一步步跳转网页操作&#xff0c;久而久之就厌烦了&#xff0c;于是花了一天时间用 Python 写了一个工具 —— PicFlow&#xff0c;从名字可以看出&am…

Web纯前端实现在线打开编辑保存PPT幻灯片

很多项目中有时会需要在线打开PPT并编辑保存到服务器。猿大师办公助手可以完美调用本地office在线打开ppt文件&#xff0c;跟本地打开效果一样。还可以在线打开word、excel、pdf等文件&#xff0c;支持本机OFFICE完整嵌入模式&#xff0c;本机OFFICE所有功能基本都可以在网页上…

Android Compose 约束布局(ConstraintLayout、Modifier.constrainAs)源码深度剖析(十二)

Android Compose 约束布局&#xff08;ConstraintLayout、Modifier.constrainAs&#xff09;源码深度剖析 一、引言 在 Android 开发中&#xff0c;布局是构建用户界面的基础。随着 Android 开发技术的不断发展&#xff0c;Jetpack Compose 作为一种全新的声明式 UI 框架应运…

常考计算机操作系统面试习题(二)(上)

目录 1. 描述分段内存管理机制 2. 解释文件分配磁盘块链接分配方法的优点和缺点 3. 进程的状态有哪些&#xff1f; 4. 一个进程的空间包括哪些部分&#xff1f; 5. 进程和程序的区别&#xff1f; 6. CPU调度可能发生在当一个进程&#xff1a; 7. 哪些条件同时出现&#…

NR SRS Configuration

文章目录 Frequency PositioningFull-Bandwidth ConfigurationFrequency-Hopping ConfigurationMulti-User ConfigurationsTime-Domain Orthogonal SRSCyclic-Shift Orthogonal SRS Summary and Further ExplorationReferences 此示例展示了如何生成探测参考信号&#xff08;SR…

【行测】言语理解与表达:选词填空

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;读不在三更五鼓&#xff0c;功只怕一曝十寒。 > 目标&#xff1a;掌握选词填空的基本题型&#xff0c;并能运用到例题中。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! …

AWS AI中几个重要的工具介绍

Amazon Bedrock Amazon Bedrock 是使用基础模型构建和扩展生成式 AI 应用程序的最简单方式。Amazon Bedrock 是一项全托管服务&#xff0c;通过 API 提供来自亚马逊和领先 AI 初创公司的基础模型&#xff0c;因此您可以从各种基础模型中选择最适合您用例的模型。借助 Bedrock&…

[项目]基于FreeRTOS的STM32四轴飞行器: 十.检测遥控器

基于FreeRTOS的STM32四轴飞行器: 十.检测遥控器 一.检测遥控器连接逻辑二.遥控器的解锁情况三.遥控器控制飞机运转 一.检测遥控器连接逻辑 判断是否进入定高模式&#xff1a; 根据返回值判断遥控器的连接情况&#xff1a; 实现检测函数&#xff1a; 因为该函数在通信任务中…

Torch.expand等效矩阵相乘

文章目录 1. description2. pytorch 1. description torch.expand:主要作用是将向量按照指定维度进行复制&#xff0c;expand 可以用全一向量和给定向量以矩阵相乘的方式等效表示n_expand4 2. pytorch torch import torch import torch.nn as nntorch.set_printoptions(pr…

尝试在软考65天前开始成为软件设计师-计算机网络

OSI/RM 七层模型 层次名功能主要协议7应用层实现具体应用功能 FTP(文件传输)、HTTP、Telnet、 POP3(邮件)SMTP(邮件) ------- DHCP、TFTP(小文件)、 SNMP、 DNS(域名) 6表示层数据格式,加密,压缩.....5会话层建立,管理&终止对话4传输层端到端连接TCP,UDP3网络层分组传输&a…

Java 双端队列实战 实现滑动窗口 用LinkedList的基类双端队列Deque实现 洛谷[P1886]

集合 关系 介绍 Deque 是一个接口 LinkedList 是这个接口的实现类 题目 输入输出 滑动窗口 基于双端队列实现 Deque<Integer> deque new LinkedList<>(); 滑动窗口代码 洛谷 public static List<Integer> maxSlidingWindow(int[] nums, int k) {List&l…

Vue3 集成wangEditor 5

1. 依赖 pnpm install wangeditor/editor --save pnpm install wangeditor/editor-for-vuenext --save2. 在template使用wangEditor 5 v-model数据库中查询出来的editor中的数据&#xff0c;数据库中使用longtext类型 <Toolbarstyle"border-bottom: 1px solid #ccc&q…

Qemu-STM32(十):STM32F103开篇

简介 本系列博客主要描述了STM32F103的qemu模拟器实现&#xff0c;进行该项目的原因有两点: 作者在高铁上&#xff0c;想在STM32F103上验证一个软件框架时&#xff0c;如果此时掏出开发板&#xff0c;然后接一堆的线&#xff0c;旁边的人估计会投来异样的目光&#xff0c;特别…

QT开发(6)--信号和槽

这里写目录标题 1. 信号和槽概述信号的本质槽的本质 2. 信号和槽的使用2.1 连接信号和槽2.2 文档查询 3.自定义信号和槽3.1 自定义槽3.2 自定义信号3.3 带参数的信号和槽 4. 信号和槽的断开 1. 信号和槽概述 在Qt中&#xff0c;⽤⼾和控件的每次交互过程称为⼀个事件。⽐如&quo…

【前端】Canvas画布实现在线的唇膏换色功能

【前端】Canvas画布实现在线的唇膏换色功能 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 【前端】Canvas画布实现在线的唇膏换色功能背景概述以下是我们的实现方法!第一步 — 找…

异步编程与流水线架构:从理论到高并发

目录 一、异步编程核心机制解析 1.1 同步与异步的本质区别 1.1.1 控制流模型 1.1.2 资源利用对比 1.2 阻塞与非阻塞的技术实现 1.2.1 阻塞I/O模型 1.2.2 非阻塞I/O模型 1.3 异步编程关键技术 1.3.1 事件循环机制 1.3.2 Future/Promise模式 1.3.3 协程&#xff08;Cor…