使用 Redis 实现分布式锁

1. 分布式锁的原理

在分布式系统中,多个进程或服务可能同时访问共享资源,为了避免资源竞争,需要一种机制来确保同一时间只有一个进程可以执行某个关键操作。Redis 提供了实现分布式锁的能力,其核心原理如下:

  • 原子性操作:Redis 的 SET 命令支持 NX(不存在时设置)和 PX(设置过期时间)参数,可以确保在设置锁时是原子的。
  • 唯一标识:每个请求生成一个唯一的标识符(如 UUID),用于标识锁的持有者,避免误删其他进程的锁。
  • 锁的释放:使用 Lua 脚本确保只有锁的持有者才能释放锁,避免误删锁。
2. 实现步骤
  1. 获取锁
    • 使用 SET 命令尝试设置一个键值对,如果键不存在则设置成功,返回 OK,表示获取锁成功。
    • 设置锁的过期时间,避免锁被永久占用。
  2. 释放锁
    • 使用 Lua 脚本检查锁的持有者是否与当前请求的标识符一致,如果一致则删除锁。
3. 示例代码

以下是一个使用 Spring Boot 和 Redis 实现分布式锁的完整示例。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;@Service
public class DistributedLockService {@Autowiredprivate StringRedisTemplate redisTemplate; // 注入 Redis 客户端private static final String LOCK_KEY = "resource_lock"; // 锁的键名private static final int LOCK_EXPIRE_TIME = 30000; // 锁的过期时间,单位毫秒/*** 获取分布式锁** @param requestId 请求的唯一标识符(如 UUID)* @return true 表示获取锁成功,false 表示获取锁失败*/public boolean acquireLock(String requestId) {// 使用 setIfAbsent 方法尝试设置锁,如果锁不存在则设置成功// 参数说明:// LOCK_KEY: 锁的键名// requestId: 锁的值,用于标识锁的持有者// LOCK_EXPIRE_TIME: 锁的过期时间// TimeUnit.MILLISECONDS: 时间单位(毫秒)Boolean result = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, requestId, LOCK_EXPIRE_TIME, TimeUnit.MILLISECONDS);return result != null && result; // 返回是否成功获取锁}/*** 释放分布式锁** @param requestId 请求的唯一标识符(如 UUID)* @return true 表示释放锁成功,false 表示释放锁失败*/public boolean releaseLock(String requestId) {// 使用 Lua 脚本确保只有锁的持有者才能释放锁// 脚本逻辑:// 1. 检查锁的值是否与当前请求的标识符一致// 2. 如果一致,则删除锁;否则返回 0String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);// 执行 Lua 脚本// 参数说明:// redisScript: Lua 脚本// Collections.singletonList(LOCK_KEY): 脚本的键参数(锁的键名)// requestId: 脚本的参数值(锁的持有者标识符)Long result = redisTemplate.execute(redisScript, Collections.singletonList(LOCK_KEY), requestId);return result != null && result == 1; // 返回是否成功释放锁}// 业务逻辑示例public void performTask() {String requestId = UUID.randomUUID().toString();try {if (acquireLock(requestId)) {// 获取锁成功,执行业务逻辑System.out.println("Lock acquired, executing critical section...");// 模拟业务逻辑Thread.sleep(1000);} else {// 获取锁失败System.out.println("Failed to acquire lock.");}} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放锁if (releaseLock(requestId)) {System.out.println("Lock released.");} else {System.out.println("Failed to release lock.");}}}}
4. 代码分析
  • 获取锁
    • 使用 setIfAbsent 方法尝试设置锁,如果锁不存在则设置成功,并设置过期时间。
    • 返回 true 表示获取锁成功,false 表示获取锁失败。
  • 释放锁
    • 使用 Lua 脚本检查锁的持有者是否与当前请求的标识符一致,如果一致则删除锁。
    • 返回 true 表示释放锁成功,false 表示释放锁失败。
  • 业务逻辑
    • 在获取锁成功后执行业务逻辑,确保同一时间只有一个进程可以执行关键操作。
    • finally 块中释放锁,确保锁一定会被释放。
5. 注意事项
  • 锁的过期时间:设置合理的过期时间,避免锁被永久占用。
  • 锁的唯一标识:每个请求生成唯一的标识符,避免误删其他进程的锁。
  • 锁的释放:使用 Lua 脚本确保只有锁的持有者才能释放锁,避免误删锁。
6. 总结

通过 Redis 实现分布式锁是一种简单有效的方式,可以确保在分布式系统中同一时间只有一个进程可以执行关键操作。结合 Spring Boot 和 Redis,可以轻松实现分布式锁,并通过设置合理的过期时间和唯一标识来管理锁的生命周期。

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

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

相关文章

IRI 2016 模型在线版 MATLAB

IRI官网&#xff1a;International Reference Ionosphere IRI-2016在线计算&#xff1a;IRI 2016 | CCMC 官方提供的MATLAB代码需要联网读取IRI网页数据&#xff1a; 下载需要注册账号&#xff0c;没有注册账号的自行注册&#xff0c;下载好后解压是这样的&#xff1a; 下载I…

数据结构系列一:初识集合框架+复杂度

前言 数据结构——是相互之间存在一种或多种特定关系的数据元素的集合。数据结构是计算机专业的基础课程&#xff0c;但也是一门不太容易学好的课&#xff0c;它当中有很多费脑子的东西&#xff0c;之后在学习时&#xff0c;你若碰到了困惑或不解的地方 都是很正常的反应&…

智慧物业平台(springboot小程序论文源码调试讲解)

第4章 系统设计 用户对着浏览器操作&#xff0c;肯定会出现某些不可预料的问题&#xff0c;但是不代表着系统对于用户在浏览器上的操作不进行处理&#xff0c;所以说&#xff0c;要提前考虑可能会出现的问题。 4.1 系统设计思想 系统设计&#xff0c;肯定要把设计的思想进行统…

2024年国赛高教杯数学建模A题板凳龙闹元宵解题全过程文档及程序

2024年国赛高教杯数学建模 A题 板凳龙闹元宵 原题再现 “板凳龙”&#xff0c;又称“盘龙”&#xff0c;是浙闽地区的传统地方民俗文化活动。人们将少则几十条&#xff0c;多则上百条的板凳首尾相连&#xff0c;形成蜿蜒曲折的板凳龙。盘龙时&#xff0c;龙头在前领头&#x…

在PyCharm中集成AI编程助手并嵌入本地部署的DeepSeek-R1模型:打造智能开发新体验

打造智能开发新体验&#xff1a;DeepSeekPycharmollamaCodeGPT 目录 打造智能开发新体验&#xff1a;DeepSeekPycharmollamaCodeGPT前言一、什么是ollama&#xff1f;二、如何使用1.进入ollama官方网站:2.点击下载ollama安装包3.根据默认选项进行安装4.安装成功5.打开命令提示符…

软件测试的基础入门(一)

文章目录 一、什么是软件测试&#xff1f;&#xff08;1&#xff09;生活中的测试案例&#xff08;2&#xff09;代码中的测试示例&#xff08;3&#xff09;软件测试的定义 二、软件测试的重要性三、测试工程师&#xff08;1&#xff09;定义&#xff08;2&#xff09;分类&am…

Linux版本控制器Git【Ubuntu系统】

文章目录 **前言**一、版本控制器二、Git 简史三、安装 Git四、 在 Gitee/Github 创建项目五、三板斧1、git add 命令2、git commit 命令3、git push 命令 六、其他1、git pull 命令2、git log 命令3、git reflog 命令4、git stash 命令 七、.ignore 文件1、为什么使用 .gitign…

20250221 NLP

1.向量和嵌入 https://zhuanlan.zhihu.com/p/634237861 encoder的输入就是向量&#xff0c;提前嵌入为向量 二.多模态文本嵌入向量过程 1.文本预处理 文本tokenizer之前需要预处理吗&#xff1f; 是的&#xff0c;文本tokenizer之前通常需要对文本进行预处理。预处理步骤可…

Spring Boot 3 整合 Spring Cloud Gateway 工程实践

引子 当前微服务架构已成为中大型系统的标配&#xff0c;但在享受拆分带来的敏捷性时&#xff0c;流量治理与安全管控的复杂度也呈指数级上升。因此&#xff0c;我们需要构建微服务网关来为系统“保驾护航”。本文将会通过一个项目&#xff08;核心模块包含 鉴权服务、文件服务…

flutter项目构建常见问题

最近在研究一个验证码转发的app&#xff0c;原理是尝试读取手机中对应应用的验证码进行自动转发。本次尝试用flutter开发&#xff0c;因为之前没有flutter开发的经验&#xff0c;遇到了诸多环境方面的问题&#xff0c;汇总一些常见的问题如下。希望帮助到入门的flutter开发者&a…

Classic Control Theory | 12 Real Poles or Zeros (第12课笔记-中文版)

笔记链接&#xff1a;https://m.tb.cn/h.Tt876SW?tkQaITejKxnFLhttps://m.tb.cn/h.Tt876SW?tkQaITejKxnFL

图解感知机(Perceptron)

目录 1.感知机&#xff08;Perceptron&#xff09;介绍 2.网络结构与工作原理 3.模型工作示例 4.总结 1.感知机&#xff08;Perceptron&#xff09;介绍 感知机&#xff08;Perceptron&#xff09;是最早的人工神经网络模型之一&#xff0c;由弗兰克罗森布拉特&#xff08;…

多旋翼+航模+直升机:多型号无人机飞行表演技术详解

多旋翼、航模、直升机等多种型号的无人机飞行表演技术&#xff0c;是现代科技与艺术的完美结合&#xff0c;它们通过精密的编程、高效的通信、先进的定位与导航技术&#xff0c;以及复杂的编队控制算法&#xff0c;共同呈现出令人震撼的视觉效果。以下是对这些无人机飞行表演技…

deepseek 导出导入模型(docker)

前言 实现导出导入deepseek 模型。deepseek 安装docker下参考 docker 导出模型 实际生产环境建议使用docker-compose.yml进行布局&#xff0c;然后持久化ollama模型数据到本地参考 echo "start ollama" docker start ollama#压缩容器内文件夹&#xff0c;然后拷贝…

【MySQL】表的增删查改(CRUD)(上)

个人主页&#xff1a;♡喜欢做梦 欢迎 &#x1f44d;点赞 ➕关注 ❤️收藏 &#x1f4ac;评论 CRUD&#xff1a;Create&#xff08;新增数据&#xff09;、Retrieve&#xff08;查询数据&#xff09;、Update&#xff08;修改数据&#xff09;、Delete&#xff08;修改数据…

Win11作为宿主机,运行VMware 总没有网络

问题&#xff1a; 移动了VMware到新宿主机上后&#xff0c;虚拟机无法连接网络&#xff0c;其实会显示一个圆圈的图标&#xff0c;这是连接上的图标。 造成这个错误的原因是多种多样的。 用下面的方法来查排查错误。 1.控制面板-> 网络连接 安装好虚拟机后&#xff0c;会…

edge浏览器将书签栏顶部显示

追求效果&#xff0c;感觉有点丑&#xff0c;但总归方便多了 操作路径&#xff1a;设置-外观-显示收藏夹栏-始终

快速入门——第三方组件element-ui

学习自哔哩哔哩上的“刘老师教编程”&#xff0c;具体学习的网站为&#xff1a;10.第三方组件element-ui_哔哩哔哩_bilibili&#xff0c;以下是看课后做的笔记&#xff0c;仅供参考。 第一节 组件间的传值 组件可以有内部Data提供数据&#xff0c;也可由父组件通过prop方式传…

代码审计入门学习之sql注入

路由规则 入口文件&#xff1a;index.php <?php // ---------------------------------------------------------------------- // | wuzhicms [ 五指互联网站内容管理系统 ] // | Copyright (c) 2014-2015 http://www.wuzhicms.com All rights reserved. // | Licensed …

基于vue和微信小程序的校园自助打印系统(springboot论文源码调试讲解)

第3章 系统设计 3.1系统功能结构设计 本系统的结构分为管理员和用户、店长。本系统的功能结构图如下图3.1所示&#xff1a; 图3.1系统功能结构图 3.2数据库设计 本系统为小程序类的预约平台&#xff0c;所以对信息的安全和稳定要求非常高。为了解决本问题&#xff0c;采用前端…