Redis 篇-深入了解基于 Redis 实现分布式锁(解决多线程安全问题、锁误删问题和确保锁的原子性问题)

Redis 分布式锁解决并发问题的方法详解 在分布式系统中,由于多个节点同时对共享资源进行操作,可能会导致并发问题。为了解决这个问题,可以使用 Redis 分布式锁来保证在同一时刻只有一个节点能够访问共享资源。本文将介绍 Redis 分布式锁的实现原理和使用方法,帮助你解决并发问题。通过本文的介绍,你了解了如何使用 Redis 分布式锁来解决并发问题。你学习了 Redis 分布式锁的实现原理和使用方法,以及一个示例代码展示了如何使用 RedisDistributedLock 类来获取和释放锁。 阅读详情

🔥博客主页: 【小扳_-优快云博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 分布式锁概述

        1.1 Redis 分布式锁实现思路

        1.2 实现基本的分布式锁

        2.0 Redis 分布式锁误删问题

        2.1 解决 Redis 分布式锁误删问题

        3.0 Redis 分布式锁原子性问题

        3.1 Lua 脚本解决多条命令原子性问题

        4.0 基本 Redis 实现的分布式锁代码


        1.0 分布式锁概述

        分布式锁是一种用于在分布式系统中控制对共享资源的访问的机制。它确保在同一时间只有一个进程或线程能够访问特定的资源,从而避免数据冲突和不一致性。

        当项目部署到集群中,如果只用 sychronized 锁是不足以在集群环境中确保线程安全,简单的说一下原因:在集群中,有多个 JVM ,就会有多个字符串常量池,锁的作用域仅限于当前 JVM 的对象或类。当多个 JVM 访问同一个资源时,每个 JVM 都会有自己的锁,导致无法实现对共享资源的有效控制。所以出现锁不住资源的情况。

        因此需要用分布式锁来完成。

常见的实现方式:

        1)数据库锁:利用数据库的事务机制来实现锁定。

        2)Redis 锁:使用 Redis 的 setnx 命令来实现分布式锁。

        3)Zookeeper 锁:利用 Zookeeper 的临时节点和顺序节点来实现分布式锁。

        1.1 Redis 分布式锁实现思路

        使用 Redis 的 SETNX 命令来实现分布式锁。

        首先,先介绍 setnx 的特性,一旦使用 setnx 设置某一个字段时,当设置成功之后再使用 setnx 设置重复字段,则会出现失败情况。Redis 分布式锁就是利用该特性来实现锁。当然,这只是大概的情况,还有很多细节需要注意。

        1)尝试获取锁的思路:

        先使用 setnx 设置某一个字段,如果返回值为成功,则获取锁成功;如果返回值为失败,则获取锁失败,那么获取锁失败可以根据具体业务情况来安排,比如可以先等待一段时间,接着再去尝试获取锁、还可以直接抛出异常等。

        还要考虑一种情况,当出现锁忘记释放了,则该字段就会一直存在缓存中,随着时间积累,缓存空间就会慢慢的减少,因此,给该字段设置 TTL ,超时时间。

        2)释放锁的思路:

        一般来说,直接用 del 命令,删除某一个字段即可。

        以上获取锁和释放锁都是最基础的形态,还有很多情况需要考虑,因此还不能在实战中使用。

        1.2 实现基本的分布式锁

尝试获取锁:

import cn.hutool.core.util.BooleanUtil;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

public class RedisLock{

    private final StringRedisTemplate stringRedisTemplate;
    private final String name;
    private static final String KEY_PREFIX = "lock:";

    public RedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    /**
     * 尝试获取锁
     * @param time
     * @param unit
     * @return
     */
    public boolean tryLock(long time,TimeUnit unit){

        long threadId = Thread.currentThread().getId();
        Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId + "", time, unit);
        return BooleanUtil.isTrue(b);
    }

    
}

        在创建 RedisLock 对象的时候,需要转递 StringRedisTemplate 类型对象,还有业务名称 name 作为锁绑定的具体对象,且在设置 setnx 的时候,value 设置为当前线程 id ,有助于查看当前锁被那一个线程获取了。最后需要注意,不可直接将类型 Boolean 类型的对象直接返回,因为由 Boolea 会自动拆箱 boolean 基本类型对象,在拆箱过程中容易出现空指针异常。

释放锁:

import cn.hutool.core.util.BooleanUtil;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

public class RedisLock{

    private final StringRedisTemplate stringRedisTemplate;
    private final String name;
    private static final String KEY_PREFIX = "lock:";

    public RedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    /**
     * 尝试获取锁
     * @param time
     * @param unit
     * @return
     */
    public boolean tryLock(long time,TimeUnit unit){

        long threadId = Thread.currentThread().getId();
        Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId + "", time, unit);
        return BooleanUtil.isTrue(b);
    }


    /**
     * 释放锁
     */
    public void unLock(){
        stringRedisTemplate.delete(KEY_PREFIX+name);
    }

}

        2.0 Redis 分布式锁误删问题

        在获取锁之后,正常执行完逻辑任务,再释放锁。这一过程按理来说,不会出现分布式锁被误删的情况,但是再考虑到一下情况:

        假设线程一正常获取锁之后,执行任务,但是该任务出现了阻塞情况,等待的时间较久,此时当锁到过期时间之后,就会自动被释放了,当时此时线程一还不知道当前锁被释放了,就在这时候,线程二来正常的获取锁,因为锁已经被释放了,所以线程二是可以获取锁成功的,接着,线程二获取锁之后,就开始执行任务了,此刻线程一任务执行完之后,会直接释放锁,这就出现线程一误删了线程二的锁问题。

如图:

        出现误删问题,就有可能出现多个线程获取锁的情况发生,从而出现线程安全问题,所以需要解决该问题。

        2.1 解决 Redis 分布式锁误删问题

        为了解决 Redis 分布式锁被误删的问题,可以想到的办法是:在释放锁之前,判断当前的锁 “是否” 是自己之前获取的锁,如果是,则可以直接释放锁;如果不是,则什么都不用做。

        具体如何判断当前锁 “是否” 是自己之前获取的锁呢?

        之前我们在设置 setnx 的时候,将 value 设置为线程 id ,那么就可以在释放锁的时候通过判断当前线程 id 与获取锁的时候设置 value 的线程 id 值两者是否一致。

        但是如果在集群环境中只判断线程 id 是否相同还不足以确保不会出现误删的情况发生,因为在集群环境中,有多个 JVM ,则非常有可能出现线程 id 相同的情况,所以还需要加上 UUID 来设置前缀,确保每一个 JVM 的前缀都是不一样的,结合起来就可以解决该情况了。

代码如下:

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

public class RedisLock{

    private final StringRedisTemplate stringRedisTemplate;
    private final String name;
    private static final String KEY_PREFIX = "lock:";
    private static final String VAL_PREFIX = UUID.randomUUID().toString(true) + "-";

    public RedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    /**
     * 尝试获取锁
     * @param time
     * @param unit
     * @return
     */
    public boolean tryLock(long time,TimeUnit unit){

        String value = VAL_PREFIX + Thread.currentThread().getId();
        Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, value, time, unit);
        return BooleanUtil.isTrue(b);
    }


    /**
     * 释放锁
     */
    public void unLock(){
        //先获取value值
        String newValue = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        String oldValue = VAL_PREFIX+Thread.currentThread().getId();
        //再判断两者是否相同
        if (oldValue.equals(newValue)){

            //相同情况,直接删除即可
            stringRedisTemplate.delete(KEY_PREFIX+name);
        }
        //不相同情况,什么都不做
    }

}

        3.0 Redis 分布式锁原子性问题

        由于在释放锁之前加上了,判断当前锁 "是否" 是自己的代码,从而有可能出现了原子性问题,当判断完之后,出现线程阻塞,导致释放锁时机延长,直到超过了过期时间,则锁就会被自动释放,当线程阻塞完毕之后,再来释放锁,此时有可能出现误删锁。

如图:

        因此需要保证判断锁和释放锁具有原子性,要么一起执行,要么都不执行。

        3.1 Lua 脚本解决多条命令原子性问题

        Redis 提供了 Lua 脚本功能,在一个脚本中编写多条 Redis 命令,确保多条命令执行时的原子性。 基本语法可以参数网站:Lua 教程 | 菜鸟教程 (runoob.com)

        使用 Lua 脚本语言编写 Redis 多条命令,先根据 key 来查询 value ,再判断 value 与当前线程标识是否相同,如果相同,则进行删除缓存;如果不相同,则什么都不需要做。

Lua 脚本如下:

-- 这里的 KEYS[1] 就是锁的Key,这里的ARGV[1]就是当前线程标识
-- 获取锁中的标识,判断是否与当前线程标识一致
if(redis.call('GET',KEYS[1]) == ARGV[1]) then
    -- 一致,则删除锁
    return redis.call('DEL',KEYS[1])
end
-- 不一致,则直接返回
return 0

        在 Java 中使用 StringRedisTemplate 对象来调用 execute 方法从而调用 Lua 脚本。

        需要传的参数:

        1)DefaultRedisScript 类型对象,该对象主要用来将读取 Lua 脚本。

        2)List<K> keys 数组对象,主要是传入 key 的实参,因为在 Lua 脚本中设置是形参,因此根据实际情况来传入实参。

        3)Object... args 任意对象,根据实际情况来传入除了 KEY 以外的实参。

        Lua 中的形参 KEYS[1] 对应的实参为 List<K> keys 数组对象,而形参 ARGV[1] 对应的实参为 Object... args 任意对象。

        在 Lua 中使用 redis.call() 方法,可以理解成调用该方法来实现对 Redis 操作。 

具体代码实现:

    private static final DefaultRedisScript<Long> defaultRedisScript;

    static {
        defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setLocation(new ClassPathResource("unlock.lua"));
        defaultRedisScript.setResultType(Long.class);
    }

    /**
     * 释放锁
     */
    public void unLock(){
        stringRedisTemplate.execute(defaultRedisScript,
                Collections.singletonList(KEY_PREFIX + name),
                VAL_PREFIX + Thread.currentThread().getId());
    }

        最后,使用 Lua 脚本实现对 Redis 多条命令的操作,再由 Java 读取操作 Lua 脚本语言,从而实现解决原子性问题。

        4.0 基本 Redis 实现的分布式锁代码

        解决了在集群环境下,确保线程安全问题,且解决了误删锁问题和解决原子性问题。

代码如下:

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class RedisLock{

    private final StringRedisTemplate stringRedisTemplate;
    private final String name;
    private static final String KEY_PREFIX = "lock:";
    private static final String VAL_PREFIX = UUID.randomUUID().toString(true) + "-";
    private static final DefaultRedisScript<Long> defaultRedisScript;
    static {
        defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setLocation(new ClassPathResource("unlock.lua"));
        defaultRedisScript.setResultType(Long.class);
    }

    public RedisLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }

    /**
     * 尝试获取锁
     * @param time
     * @param unit
     * @return
     */
    public boolean tryLock(long time,TimeUnit unit){

        String value = VAL_PREFIX + Thread.currentThread().getId();
        Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, value, time, unit);
        return BooleanUtil.isTrue(b);
    }


    /**
     * 释放锁
     */
    public void unLock(){
        stringRedisTemplate.execute(defaultRedisScript,
                Collections.singletonList(KEY_PREFIX + name),
                VAL_PREFIX + Thread.currentThread().getId());
    }

/*    public void unLock(){
        //先获取value值
        String newValue = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        String oldValue = VAL_PREFIX+Thread.currentThread().getId();
        //再判断两者是否相同
        if (oldValue.equals(newValue)){

            //相同情况,直接删除即可
            stringRedisTemplate.delete(KEY_PREFIX+name);
        }
        //不相同情况,什么都不做
    }*/

}

Redis实现分布式锁 1. 为什么需要分布式锁?我们都知道,以上情况,,此时就2. 单机锁 & 分布式锁的定义:3. 分布式锁应该具备哪些条件?4. 分布式锁都有哪些主流的实现方案?分布式锁的核心是实现多线程之间互斥,而满足这一点的方式有很多,常见的有三种:补充:Zookeeper实现分布式锁的思路实现分布式锁的核心思路5. 如何用 Redis 实现分布式锁的?Redis本身可以被多个客户端访问,正好就是一个共享存储系统,可以用来保存分布式锁,而且Redis的读写性能高,可以应对高并发的锁操作场景。 阅读详情

相关推荐

植物叶绿体基因组分析全攻略:从共线性到密码子偏好性

本文全面解析植物叶绿体基因组分析流程,从共线性分析到密码子偏好性研究。详细介绍了叶绿体基因组结构特征、测序数据获取与质量控制、基因组组装与注释方法,以及比较基因组学和进化分析技术。特别关注IR区边界变异分析和选择压力评估,为植物系统发育研究和物种鉴定提供实用指南。

weixin_28475533的博客 221

Redis实现分布式锁的7种方案

在分布式环境下,可以把键设置为锁的名称,把值设置为当前进程的唯一标识(例如IP地址或进程ID),这样多个进程同时尝试设置同一个键时,只有一个能够成功设置成锁,表示该进程获得了锁。RedSync的具体实现方式可以参考https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81。该方法的缺点是无法解决多进程操作的原子性问题,即在获取锁和设置过期时间这两个步骤中间可能会出现错误的情况,导致锁的状态出现问题。

wgq2020的博客 761

MaxKey+JeecgBoot单点登录实战:手把手教你从零配置到账户同步

本文提供MaxKey与JeecgBoot单点登录(SSO)的实战整合指南。详细讲解从MaxKey应用注册、JeecgBoot前后端改造,到最终实现账户同步的完整步骤,重点解决Shiro配置、令牌交换等关键问题,帮助企业构建统一、可扩展的身份管理体系。

weixin_29258297的博客 540

Redis系列:使用Redis实现分布式锁及相关问题

分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。 本篇内容包括:关于 Redis 与 分布式锁,Redis 分布式锁的问题及解决方式,Redis 中的 Lua 脚本 以及 Redis 中的 RedLock 算法!

栗筝i的博客 6358

Kubernetes CRD 系列(一):CRD 介绍

CR(Custom Resource)其实就是在 Kubernetes 中定义一个自己的资源类型,是一个具体的 “自定义 API 资源” 实例,为了能够让 Kubernetes 认识这个 CR,就需要让 Kubernetes 明白这个 CR 的宏观定义是什么,也就是需要创建所谓的 CRD(Custom Resource Definition)来表述。 可能这么说并不是太直观,换个方式表达一下,我们想要创建一个 Pod 的时候,那么会编写一个 YAML 配置,然后前两行一般会这么写: [root@l

会哭的雨@的博客 7920

Frida实战:从adb连接到安卓设备参数加密Hook全流程解析

本文详细解析了使用Frida进行安卓应用动态分析的全流程。通过adb连接设备并部署Frida服务端,结合静态分析与动态Hook技术,精准定位并拦截关键函数,特别是针对参数加密等核心逻辑的实时监控与修改,为逆向分析与安全研究提供了高效实战方案。

weixin_29208077的博客 342

Redis 做分布式锁的常见问题和解决方案

redis 做分布式锁的三个核心要素: 1、加锁 最简单的命令是setnx,key是锁的唯一标识,按业务来决定命名,value为当前线程的线程ID。当一个线程执行setnx返回1,说明key原本不存在,该线程成功得到了锁,当其他线程执行setnx返回0,说明key已经存在,该线程抢锁失败。 2、解锁 当得到锁的线程执行完任务,需要释放锁,以便其他线程可以进入。释放锁的最简单方式是执行del...

西木风落 3198

智能汽车竞赛摄像头处理(4)——摄像头循迹思路讲解

智能汽车竞赛摄像头处理(4)对摄像头循迹思路进行讲解。

weixin_62261692的博客 7057

使用 Redis 实现分布式锁,解决分布式锁原子性、死锁、误删、可重入、自动续期等问题(使用SpringBoot环境实现)

使用 Redis 实现分布式锁,解决分布式锁原子性、死锁、误删、可重入、自动续期等问题(使用SpringBoot环境实现)

kerwin的博客 1万+

开题报告该怎么写

考研即将来临,而一般很多大学都会选择在考研结束之后开始安排选题和开题报考(考研之前一般都不谈,老师也很人性化的,不愿意耽误你的复习) 但无论怎么推迟,我们最终都需要去面对并完成这些任务。 现在我就要教大家该如何写一个完整的开题报告! 准备模板。不同的学校有不同的格式,一般情况你的导师会给你们一个学校的标准格式,这个不用太费心。有了模板我们就可以按照模板的“线索”一步一步填充完成即可! 一般大致格式可谓: 研究背景/论文的目的、背景和意义 我们需要写明选择该题目的...

wuyueweifeng的博客 1095

Python学习第32天:Web前端入门

本文介绍了Web前端开发三大核心技术:HTML、CSS和JavaScript。首先概述了HTML的发展历程和HTML5新特性,详细讲解了常用HTML标签如文本、列表、链接、图像、表格、表单等。其次介绍了CSS的基础语法、选择器、颜色字体设置、盒子模型和布局定位方法。最后简要提及JavaScript为网页添加交互功能的作用。文章为Python开发者提供了前端技术的基础知识,帮助理解网页的结构、样式和行为实现原理。

tigerhhzz的博客 1910

六.Redis极简入门-Redis实现分布式锁原理

老鸟飞过,学习使用,欢迎交流 理解分布式锁 为什么要分布式锁 在并发场景中,我们可以使用加锁的手段来保证业务方法或代码的原子性操作,从而防止数据被并发修改引发安全问题,在单体应用中我们可以使用互斥锁如: synchronized 同步代码块 或者 Lock锁来实现,如图: 但是在集群/分布式应用中单纯的互斥锁是不能保证多个节点中对同一个数据的原性操作的,如图: 集群模式中,每个服务都加了锁但是只能锁住自己,每个服务做库存做扣减操作,当库存都剩1的时候,三个服务并发减库存可能会导致库存减到 -2 出现线程

墨家巨子@俏如来 1万+

Open3D——RANSAC 三维点云空间直线拟合【2025最新版】

使用RANSAC算法在点云数据中拟合三维空间直线的python代码实现。博客长期更新,本文最新更新时间为:2025年3月23日。

点云侠的博客 7354

如何在分布式环境中实现高可靠性分布式锁

通过选择合适的分布式锁实现方式,可以有效提升系统的可靠性和一致性,确保业务逻辑的正确执行。在实际应用中,需要根据具体场景选择合适的实现方式,并进行适当的优化和调整,以应对分布式环境下的复杂挑战。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 8万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Redis-分布式锁

帮助你快速理解和学习redis的分布式锁实现逻辑。

2302_77423520的博客 4439

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

redis 14 分布式锁(UUID防误删、LUA脚本保证删除的原子性、锁的实现原则)

文章目录一. 分布式锁1.1 问题描述:1.2 解决方案:使用redis实现分布式锁二.代码实现2.1 加锁:2.2 优化之设置锁的过期时间2.3 优化之UUID防误删2.3.1 场景:2.3.2 解决:2.4 优化之LUA脚本保证删除的原子性2.4.1 场景: 删除操作缺乏原子性2.4.2 解决:三. 锁的实现原则 一. 分布式锁 1.1 问题描述:   随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制

不是一枚开发 7万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【Redis】实现一个分布式锁(上)

Tomcat是一个开源的、轻量级的Web服务器和Servlet容器.Tomcat本身是一个Java应用程序,它运行在JVM中,并管理着其内部所有Web应用程序的生命周期TomcatServlet容器Tomcat作为一个Servlet容器,能够执行。Servlet是一种用于扩展Web服务器功能的Java类,它能够对来自Web客户端(如浏览器)的请求进行响应。JSP容器Tomcat还支持JSP技术,允许在HTML页面中嵌入Java代码,以动态生成Web页面。当JSP页面首次被访问时,Tomcat。

2301_78320637的博客 1231

利用Redis的SetNx一步步实现分布式锁并改进

利用set nx ex获取锁,并设置过期时间,保存线程标示释放锁时先判断线程标示是否与自己一致,一致则删除锁特性:利用set nx满足互斥性利用set ex保证故障时锁依然能释放,避免死锁,提高安全性利用Redis集群保证高可用和高并发特性。

coderge's 优快云 Blog. 5616

redis--分布式锁详解

redisson分布式锁原理:可重入:利用hash结构记录线程id和重入次数,当线程获取锁失败后去判断锁包含的线程id是否一致,如果一致,则让其获取锁,并且重入次数加一。在释放锁时,先去判断锁中的线程ID,再去判断重入次数是否为0,如果为0,则释放,不为0,则无视可重试:利用信号量和pubsub功能实现等待、唤醒、获取锁失败的重试机制。在第一次获取锁失败以后,并不是直接返回false,尝试获取锁的返回结果就是ttl(剩余有效时间),如果返回值为null。则获取锁成功,若不为null,则获取锁失败,

m0_73856804的博客 1241

分布式锁解决集群下发生的并发问题

如,在线程1完成业务后判断锁是自己的,在释放锁的时候,遇到了阻塞,如果超过了锁持有的时间,就会超时释放锁,此时线程2就可以得到锁,在执行业务的时候,线程1阻塞完成,释放了锁。,再来一个线程3,由于锁被释放了,所以线程3能够正常后去锁和执行业务,此时发生了线程2和线程3并行执行的情况,此时可能会发生线程安全问题,我们的锁意义就没有了。同时我们用非阻塞的方式来保证执行效率。,等线程1完成业务后,会执行释放锁的操作(前面我们设置的),但是锁此时在线程2上,这时线程2就会直接释放锁,

2402_83510798的博客 1092

redis--黑马点评--分布式锁实现详解

假设有两个JVM,JVM1中的线程A,来获取锁,就需要去寻找外部的锁监视器,一旦获取成功,就回去记录当前获取锁的是这个线程A,在高并发情况下,此时如果有其他线程也来获取锁,比如JVM2线程中的线程C,但因为外部的锁监视器中已经记录锁的持有者了,因此线程C获取锁失败,则需要等待锁释放,当线程A释放锁成功后,线程C来获取锁,之后执行自己的业务。线程开启,尝试获取锁,执行命令,结果有两种,OK,NIL,NIL代表失败,证明锁已经被获取,OK代表获取互斥锁成功,则执行业务,业务执行完之后,释放锁。

m0_73856804的博客 1161

Redis分布式锁实战:从误删问题到Lua脚本原子性解决方案

本文深入剖析了Redis分布式锁在实战中常见的误删问题及其根源,并重点介绍了如何利用Lua脚本的原子性特性,构建一个安全、可靠的解锁方案。通过对比非原子操作的风险与Lua脚本的解决方案,为开发者提供了从问题诊断到代码落地的完整实践指南,确保高并发场景下共享资源访问的正确性。

uu89012的博客 515

Redis实现分布式锁的原理:常见问题解析及解决方案、源码解析Redisson的使用

介绍Redis实现分布式锁的原理、常见问题解析与解决方案、源码解析Redisson的使用

qurious7的博客 3719

微服务架构之:Redis的分布式锁---搭建生产可用的Redis分布式锁

单体架构上,乐观锁和悲观锁可以锁住并发情况下的同步代码块,我们多使用synchronized来对方法加锁。但是在配上负载均衡的集群模式下,普通的synchronized是无法锁住从两台服务器同时进入的请求。JVM内部的锁监视器直接作废。所以锁的监视器一定要在JVM的外部,让所有JVM都去找独一无二的锁监视器来获取锁,这样也就只有一个线程获取锁,也就实现了多JVM的线程互斥。分布式锁核心是实现多进程之间的互斥,而满足这一点的方式有很多,常见的有三种:Mysql、Redis。

qq_53999369的博客 2855
上一篇: Redis 篇-深入了解查询缓存与缓存所带来的问题(读写不一致、缓存穿透、缓存雪崩、缓存击穿)
下一篇: Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)
小扳
小扳 优质创作者: Java技术领域 优质创作者: Java技术领域
博客等级 码龄4年 1万+粉丝 167原创
评论 37
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小扳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值