当前位置: 首页 > 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…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...