当前位置: 首页 > news >正文

[Redis 分布式锁 ]

目录

前言:  

使用场景:

基于 Redis 实现分布式锁的详细示例:

使用示例:

依赖:

Redis分布式锁控制并发访问:


前言:  

   记录一些小笔记 , 如果对你有帮助 那就更好了

使用场景:

Redis 实现分布式锁的使用场景包括:

  1. 防止重复操作:在分布式环境下,多个进程可能同时对同一个资源进行操作,为了避免重复操作,可以使用分布式锁来保证只有一个进程可以对资源进行操作。

  2. 控制并发访问:在高并发场景下,多个进程同时访问同一个资源可能会导致性能问题,为了控制并发访问,可以使用分布式锁来限制同时访问的进程数量。

  3. 保证数据一致性:在分布式事务场景下,需要保证多个操作的原子性,可以使用分布式锁来保证多个操作的顺序和一致性。

  4. 避免死锁:在分布式环境下,多个进程可能同时获取锁,为了避免死锁,可以使用分布式锁来保证只有一个进程可以持有锁。

总之,分布式锁是在分布式环境下保证数据一致性和避免并发问题的重要工具,适用于各种分布式应用场景。

基于 Redis 实现分布式锁的详细示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;public class RedisDistributedLock {private static final String LOCK_KEY = "lock_key";private static final int LOCK_EXPIRE_TIME = 30000; // 锁过期时间,单位毫秒private static final int SLEEP_TIME = 100; // 获取锁失败后,等待重试的时间,单位毫秒private Jedis jedis;public RedisDistributedLock(Jedis jedis) {this.jedis = jedis;}public boolean lock() {while (true) {SetParams params = new SetParams();params.nx();params.px(LOCK_EXPIRE_TIME);String result = jedis.set(LOCK_KEY, "locked", params);if ("OK".equals(result)) {return true;}try {Thread.sleep(SLEEP_TIME);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}public void unlock() {jedis.del(LOCK_KEY);}
}

在上面的示例中,我们使用了 Redis 的 SETNX 命令来实现分布式锁。当 SETNX 命令返回 1 时,表示成功获取到锁,否则表示锁已被其他进程占用,需要等待一段时间后重试。为了避免死锁,我们还设置了锁的过期时间,当锁过期后,其他进程可以重新获取锁。

使用示例:

import redis.clients.jedis.Jedis;public class Main {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");RedisDistributedLock lock = new RedisDistributedLock(jedis);try {if (lock.lock()) {// 获取锁成功,执行业务逻辑} else {// 获取锁失败,处理异常情况}} finally {lock.unlock();}}
}

在实际应用中,我们需要根据具体的业务需求和系统架构来调整分布式锁的实现方式。例如,可以使用 Redis 的 Lua 脚本来实现原子性操作,或者使用 Redlock 算法来提高分布式锁的可靠性。

依赖:

上述代码需要依赖 Redis 的 Java 客户端库,例如 Jedis 或 Lettuce。以下是 Maven 依赖示例:

根据实际情况选择合适的 Redis 客户端库和版本。

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.0</version>
</dependency>

<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.1.3.RELEASE</version>
</dependency>
 


Redis分布式锁控制并发访问:

Redis 分布式锁可以用来控制并发访问,避免多个进程同时访问同一个资源导致的性能问题。具体来说,可以使用 Redis 分布式锁来限制同时访问某个资源的进程数量,例如:

  1. 获取锁时,检查当前已经持有锁的进程数量,如果超过了限制数量,则等待一段时间后重试。

  2. 在释放锁时,检查是否还有其他进程在等待锁,如果有,则唤醒其中一个进程继续执行。

下面是一个使用 Redis 分布式锁控制并发访问的示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;public class RedisConcurrencyControl {private static final String LOCK_KEY = "lock_key";private static final int LOCK_EXPIRE_TIME = 30000; // 锁过期时间,单位毫秒private static final int SLEEP_TIME = 100; // 获取锁失败后,等待重试的时间,单位毫秒private static final int MAX_CONCURRENCY = 10; // 最大并发数private Jedis jedis;public RedisConcurrencyControl(Jedis jedis) {this.jedis = jedis;}public boolean acquireLock() {while (true) {SetParams params = new SetParams();params.nx();params.px(LOCK_EXPIRE_TIME);String result = jedis.set(LOCK_KEY, "locked", params);if ("OK".equals(result)) {return true;}try {Thread.sleep(SLEEP_TIME);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}public void releaseLock() {jedis.del(LOCK_KEY);String waitingKey = LOCK_KEY + "_waiting";String waitingCount = jedis.get(waitingKey);if (waitingCount != null) {int count = Integer.parseInt(waitingCount);if (count > 0) {jedis.decr(waitingKey);jedis.publish(waitingKey, "1");} else {jedis.del(waitingKey);}}}public boolean tryEnter() {String waitingKey = LOCK_KEY + "_waiting";String waitingCount = jedis.get(waitingKey);if (waitingCount == null) {jedis.set(waitingKey, "1");jedis.expire(waitingKey, LOCK_EXPIRE_TIME);return true;} else {int count = Integer.parseInt(waitingCount);if (count < MAX_CONCURRENCY) {jedis.incr(waitingKey);jedis.expire(waitingKey, LOCK_EXPIRE_TIME);return true;} else {return false;}}}public void waitEnter() {String waitingKey = LOCK_KEY + "_waiting";jedis.subscribe(new JedisPubSub() {@Overridepublic void onMessage(String channel, String message) {synchronized (RedisConcurrencyControl.this) {RedisConcurrencyControl.this.notifyAll();}}}, waitingKey);}
}

在上面的示例中,我们使用 Redis 分布式锁来控制最大并发数。在进程尝试访问资源时,首先需要获取锁,如果获取锁失败,则等待一段时间后重试。如果获取锁成功,则检查当前已经持有锁的进程数量,如果超过了最大并发数,则将自己加入等待队列,并等待其他进程释放锁后唤醒自己。在释放锁时,需要检查等待队列中是否有其他进程在等待,如果有,则唤醒其中一个进程继续执行。

使用示例:

import redis.clients.jedis.Jedis;public class Main {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");RedisConcurrencyControl control = new RedisConcurrencyControl(jedis);try {if (control.acquireLock()) {if (control.tryEnter()) {// 进程成功进入资源访问队列,执行业务逻辑} else {// 进程无法进入资源访问队列,等待其他进程释放锁control.waitEnter();}} else {// 获取锁失败,处理异常情况

Redis文档学习地址:  必须点个三连好吧, 步步高升 7. 分布式集合 - 7.1. 映射(Map) - 《Redisson 使用手册》 - 书栈网 · BookStack

相关文章:

[Redis 分布式锁 ]

目录 前言: 使用场景: 基于 Redis 实现分布式锁的详细示例&#xff1a; 使用示例&#xff1a; 依赖: Redis分布式锁控制并发访问: 前言: 记录一些小笔记 , 如果对你有帮助 那就更好了 使用场景: Redis 实现分布式锁的使用场景包括&#xff1a; 防止重复操作&#xf…...

如何创建Vue实例?Vue实例有哪些属性和方法

Vue实例就是Vue的实例化对象&#xff0c;就像你有一个iPhone&#xff0c;那么iPhone就是你的实例化对象。要创建Vue实例&#xff0c;就像你想拥有一部iPhone一样&#xff0c;首先要有一个设计图。 这个设计图就相当于Vue实例的options对象&#xff0c;你可以设置它的属性&…...

InnoDB Cluster集群Mysql Router代理层最佳实践

InnoDB Cluster 集群 & Mysql-Router 代理层 前言 Mysql是现今最常用的关系型数据库之一&#xff0c;高可用一直是我们对软件服务的要求。常见的Mysql高可用是主从配置&#xff0c;在主节点挂掉后需要依赖监控脚本进行主从切换将从节点升级&#xff0c;后台服务代码层面也…...

RabbitMQ系列-概念及安装

1. 消息队列 消息队列是指利用队列这种数据结构进行消息发送、缓存、接收&#xff0c;使得进程间能相互通信&#xff0c;是点对点的通信 而消息代理是对消息队列的扩展&#xff0c;支持对消息的路由&#xff0c;是发布-订阅模式的通信&#xff0c;消息的发送者并不清楚消息的…...

进程间通信之共享内存

进程间通信之共享内存 1.共享内存机制2.两种常用共享内存方式3.补充一下:linux中shm与shmm的区别4.IPC通信System V版本的共享内存shm5.存储映射共享I/O(mmap函数)1.共享内存机制 是允许两个或多个进程(不相关或有亲缘关系)访问同一个逻辑内存的机制。它是共享和传递数据的一…...

网络连接中的舔狗协议

舔狗网络协议 &#xff08;discard protocol) 最近互联网上&#xff0c;“舔狗” 这个词语很火&#xff0c;也衍生出来很多梗&#xff08;快速说出互联网 4 大舔狗&#xff01;&#xff01;&#xff01;&#xff09;。然后今天偶然间看到了一个 RFC 文档&#xff0c; 发现了一…...

一分钟了解乐观锁、悲观锁、共享锁、排它锁、行锁、表锁以及使用场景

大家好&#xff0c;我是冰点&#xff0c;今天给大家带来&#xff0c;关于MySQL中的锁的使用。 我首先提个问题&#xff0c;大家知道什么是 乐观锁、悲观锁、共享锁&#xff0c;、排它锁、行锁、表锁&#xff0c;以及每种锁的使用场景吗&#xff1f; !! 背景&#xff1a;最近在各…...

【C++】C++ 中的 IO 流

文章目录 一、C语言的输入输出二、什么是流三、C IO 流1、C 标准 IO 流2、C 文件 IO 流 四、stringstream 介绍 一、C语言的输入输出 在C语言中我们使用最频繁的输入输出方式是 scanf () 与 printf()&#xff1a; scanf()&#xff1a;从标准输入设备 (键盘) 读取数据&#xf…...

QFuture的使用

QFuture 是 Qt 提供的一个类&#xff0c;用于表示异步操作的返回值或状态。异步操作指的是那些不会阻塞主线程的操作&#xff0c;例如文件读写、网络请求、计算等等。 在执行异步操作时&#xff0c;可以使用 QtConcurrent 模块提供的函数 (QFuture<T> QtConcurrent::run…...

通过dockerfile将nginx、前端和后端封装成一个镜像

1、内容如下 2、dist文件 就是vue项目的打包文件 3、jar包文件 就是springboot的打包文件 4、编写Dockerfile #引用 jdk1.8作为基础镜像,这个jdk1.8是我自己用linux版本的jdk打包的,具体操作可以看 #https://blog.csdn.net/qq_38639813/article/details/129384923中将jd…...

如何利用CiteSpace快速锁定领域内最新研究热点并制作精美的可视化专题图?

【基于Citespace和vosviewer文献计量学相关论文 】 ​ 01 文献计量学方法与应用 1. 文献计量学方法基本介绍 2. 与其他综述方法区别联系 3. 各学科领域应用趋势近况 4. 主流分析软件优缺点对比 5. 经典高分10SCI思路复盘 6. 软件安装与Java环境配置 02 主题确定、数据检…...

嵌入式开发从入门到精通之第二十二节:蓝牙芯片CC254x ADC 电压测量

目录 1. CC254x ADC原理 参考电压 采样通道 采样率 采样时间...

北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 一.讲解 要想实现二叉树的路径显示&#xff0c;我们要按照…...

vue 3 第二十八章:组件十二(组件的v-model、多v-model)

文章目录 1. 基本使用2. 使用conputed实现3. v-model 的参数4. 多 v-model 的使用5. v-model 修饰符 在 Vue 3 中&#xff0c; v-model 指令的使用更加灵活&#xff0c;可以绑定任意属性和事件。例如&#xff0c;我们可以使用 v-model:checked 指令来绑定单选框或复选框的 c…...

LCD 显示

概述 LCD显示控制模块接收 MCU 送过来的数据&#xff0c;按一定规律储存在显示 RAM 中&#xff0c;并根据显示 RAM 中的数据驱动 LCD 显示屏来实现期望的字符显示功能。 主要特点&#xff1a; ⚫ 最大支持 840 、 642 、 444 的显示段数 ⚫ 1/3bias 、 1/4bia s ⚫ 16 级灰度可…...

互联网医院开发|在线问诊系统架构设计功能有哪些?

互联网医院会增加更多的医疗业务&#xff0c;电话问诊、视频问诊、个性化的医疗套餐等&#xff0c;未来互联网医院会建成围绕健康主题的深度大数据平台和多元化医疗服务生态体系&#xff0c;丰富人工智能、物联网等应用场景&#xff0c;为用户提供更好的服务体验、更低的成本、…...

数据安全运营有效管理-数据安全复合治理框架和模型解读(1)

数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地运营管理水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理要充分考…...

【刷题之路】LeetCode 面试题 03.02. 栈的最小值

【刷题之路】LeetCode 面试题 03.02. 栈的最小值 一、题目描述二、解题1、方法1——“辅助栈”1.1、思路分析1.2、代码实现 一、题目描述 原题连接&#xff1a; 面试题 03.02. 栈的最小值 题目描述&#xff1a; 请设计一个栈&#xff0c;除了常规栈支持的pop与push函数以外&am…...

如何处理图片排重(精准排重,相似排重)

图片相似度对比 1、需求 假如有一个图片池&#xff0c;存有1亿图片。给一张目标图片&#xff0c;在图片池中做匹配。 判断一张图片是否在图片池中出现过。&#xff08;完全一样&#xff09;判断有没有相似的出现过。比如两张图相似度90&#xff0c;两张图片是在描述一件事情。 …...

盐城北大青鸟“北大青鸟杯”IT精英挑战赛设中心评审隆重开赛

为积极响应北大青鸟总部开展第十届“北大青鸟杯”全国IT精英挑战赛的号召&#xff0c;成就学员们的IT梦想&#xff0c;“北大青鸟杯”IT精英挑战赛&#xff08;设计组&#xff09;盐城卓晨中心评审于2023年5月25日下午1:00在人才大厦306教室正式开赛&#xff01; ​ 赛前&a…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...