手写一个简单的redis分布式锁

【并发编程】基于 Redis 手写分布式锁 在集群的情况下,如果客户端发送请求到主服务器获取锁,此时主服务器还没来得及向从服务器同步获取锁的状态,主服务器就发生了宕机。此时客户端再次请求服务器到主服务器(由从服务器选主升级为主服务器),由于之前没有同步锁的状态,获取到另一把全新的锁,导致锁的失效,引发超卖现象。​:如果一个线程已经持有了锁,在执行过程中又尝试再次获取该锁(例如递归调用场景下),由于默认的分布式锁实现通常是不支持重入的,第二次获取锁时会失败,进而可能导致死锁(比如线程在持有锁的情况下递归调用自身,每次调用都尝试获取锁但获取不到) 阅读详情

定义一个获取锁的方法 lock方法

 /**
     * 获取锁
     *
     * @param key         key
     * @param expire      获取锁超时时间
     * @param retryTimes  重试次数
     * @param sleepMillis 获取锁失败的重试间隔
     * @return 成功/失败
     */
    boolean lock(String key, long expire, int retryTimes, long sleepMillis);

lock方法的实现

@Override
    public boolean lock(String key, long expire, int retryTimes, long sleepMillis) {
        boolean result = setRedis(key, expire);
        // 如果获取锁失败,按照传入的重试次数进行重试
        while (!result && retryTimes-- > 0) {
            try {
                log.debug("get redisDistributeLock failed, retrying..." + retryTimes);
                Thread.sleep(sleepMillis);
            } catch (InterruptedException e) {
                log.warn("Interrupted!", e);
                Thread.currentThread().interrupt();
            }
            result = setRedis(key, expire);
        }
        return result;
    }

setRedis方法

 private final ThreadLocal<String> lockFlag = new ThreadLocal<>();
 
 private boolean setRedis(final String key, final long expire) {
        try {
            return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
                String uuid = UUID.randomUUID().toString();
                lockFlag.set(uuid);
                byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                byte[] uuidByte = redisTemplate.getStringSerializer().serialize(uuid);
                return (boolean) connection.set(keyByte, uuidByte, Expiration.from(expire, TimeUnit.MILLISECONDS),
                        RedisStringCommands.SetOption.ifAbsent());
            });
        } catch (Exception e) {
            log.error("设置redis锁发生异常", e);
        }
        return false;
    }

释放锁

/**
     * 释放锁
     *
     * @param key key值
     * @return 释放结果
     */
    boolean releaseLock(String key);

 private static final String UNLOCK_LUA;

    /*
     * 通过lua脚本释放锁,来达到释放锁的原子操作
     */
    static {
        UNLOCK_LUA = "if redis.call(\"get\",KEYS[1]) == ARGV[1] " +
                "then " +
                "    return redis.call(\"del\",KEYS[1]) " +
                "else " +
                "    return 0 " +
                "end ";
    }


@Override
    public boolean releaseLock(String key) {
        // 释放锁的时候,有可能因为持锁之后方法执行时间大于锁的有效期,此时有可能已经被另外一个线程持有锁,所以不能直接删除
        try {
            // 使用lua脚本删除redis中匹配value的key,可以避免由于方法执行时间过长而redis锁自动过期失效的时候误删其他线程的锁
            // spring自带的执行脚本方法中,集群模式直接抛出不支持执行脚本的异常,所以只能拿到原redis的connection来执行脚本
            return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
                byte[] scriptByte = redisTemplate.getStringSerializer().serialize(UNLOCK_LUA);
                return connection.eval(scriptByte, ReturnType.BOOLEAN, 1
                        , redisTemplate.getStringSerializer().serialize(key)
                        , redisTemplate.getStringSerializer().serialize(lockFlag.get()));
            });
        } catch (Exception e) {
            log.error("释放redis锁发生异常", e);
        } finally {
            lockFlag.remove();
        }
        return false;
    }
Redis实战之 分布式锁 重入问题:重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁,比如HashTable这样的代码中,他的方法都是使用synchronized修饰的,假如他在一个方法内,调用另一个方法,那么此时如果是不可重入的,不就死锁了吗?所以可重入锁他的主要意义是防止死锁,我们的synchronized和Lock锁都是可重入的。不可重试:是指目前的分布式只能尝试一次,我们认为合理的情况是:当线程在获得锁失败后,他应该能再次尝试获得锁。 阅读详情

相关推荐

如何选择StandardScaler、MinMaxScaler和RobustScaler做标准化的对比解释和示例代码

选择合适的标准化方法取决于数据的特点和需求。如果数据分布接近正态分布且无异常值,可以使用。如果需要将数据映射到特定范围内并保持相对关系,可以使用。如果数据中存在异常值或离群点,可以使用进行鲁棒标准化。在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,StandardScaler表现更好(避免不同量纲对方差、协方差计算的影响);在不涉及距离度量、协方差、数据不符合正态分布、异常值较少的时候,可使用MinMaxScaler。

qq_36001281的博客 4941

第十九章_手写Redis分布式锁

在目标锁对象的计数器不为零的情况下,如果锁对象的持有线程是当前线程,那么 Java 虚拟机可以将其计数器加1,否则需要等待,直至持有线程释放该锁。是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提,锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞。不同进程jvm层面的锁就不管用了,那么可以利用第三方的一个组件,来获取锁,未获取到锁,则阻塞当前想要运行的线程。指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁,这样的锁就叫做可重入锁。

sinat_31583645的博客 1080

单细胞数据pseudobulks差异分析实战:从聚合到DESeq2

本文详细介绍了单细胞转录组数据分析中pseudobulks(伪散装)方法的实战流程。通过将同一样本的同类型细胞表达值聚合,模拟Bulk RNA-seq数据,再利用DESeq2进行稳健的差异基因分析。该方法有效降低了单细胞数据的技术噪音,特别适用于样本量有限但追求结果稳定性的研究场景,并提供了完整的R代码实现与结果解读指南。

sea99的博客 761

手写Redis分布式锁(一)

​ 假设在购物场景,有两个服务同时让库存减少,那么普通的synchronize或者lock就不起作用了,因为synchronize只能保证一个jvm里的线程安全,此时两个服务处于不同的jvm中,资源类(库存)在不同的服务器之间共享了,这时synchronize就会失效,所以需要分布式锁来解决这个问题。​ 在案例二中,我们貌似已经实现了分布式锁,但仍旧这样一个问题:在删除锁时,if判断与删除操作并不具备。客户端加锁之后,如果没有主动释放自己创建的锁(只能释放自己所创建的锁,为了。表示创建一个键值对为。

a695484357的博客 640

DPO(Direct Preference Optimization)直接偏好优化

本文介绍了DPO(直接偏好优化)方法,该方法通过简化传统的RLHF(基于人类反馈的强化学习)流程,直接利用人类偏好数据进行模型优化。DPO的核心思想是跳过奖励模型训练和强化学习交互步骤,通过数学推导将优化目标转化为仅与策略概率分布相关的形式。推导表明最优策略与奖励模型之间存在显式关系,从而可以构建直接优化策略的损失函数。与RLHF相比,DPO简化了训练流程,提高了工程实现稳定性,同时保持了同等效果。

TeenLucifer的博客 1956

053、坏点校正(DPC)进阶:静态坏点标定与动态坏点检测算法对比

文章摘要: 本文深入探讨了图像传感器坏点校正(DPC)技术,重点对比静态坏点标定与动态坏点检测算法。作者结合真实案例,指出静态标定在高增益场景下的局限性,并详细解析动态检测的核心算法、参数调优及常见误检问题(如边缘/纹理干扰)。提出“静态为主+动态为辅”的混合方案,强调阈值需随增益、亮度和温度自适应调整。文末总结六条工程建议,包括避免固定阈值、优先使用中值替换、定期更新坏点表等,强调DPC是图像质量的基础防线,需结合传感器特性综合优化。

zzfmlxs的博客 264

手写Redis分布式锁

手写Redis分布式锁

xiaguxiagu的博客 1801

基于Simulink的无线充电系统LCC补偿网络建模与控制

本文详细介绍了基于Simulink的无线充电系统LCC补偿网络建模与控制方法。首先分析了无线充电系统面临的核心挑战,提出LCC补偿网络解决方案,阐述了其恒流输出和输入阻抗解耦原理。通过Simulink分步演示了系统建模过程,包括松耦合变压器、LCC+LC补偿网络、功率变换级搭建以及频率跟踪控制实现。仿真结果表明,LCC补偿系统在气隙变化和负载跳变下能保持输出电压稳定(波动±3%),效率达89%。文章还总结了工程实现要点,并探讨了动态充电、多负载系统等扩展应用。该教程为开发高效智能的无线充电系统提供了实用指导

amy_mhd的博客 63

Redis7实战加面试题-高阶篇(手写Redis分布式锁)

1.synchronized,单机版oK,上分布式死翘翘2.nginx分布式微服务单机锁不行3.取消单机锁,上redis分布式锁setnx只加了锁,没有释放锁,出异常的话,可能无法释放锁,必须要在代码层面finally释放锁宕机了,部署了微服务代码层面根本没有走到finally这块,没办法保证解锁,这个key没有被删除,需要有lockKey的过期时间设定为redis的分布式锁key,增加过期时间此外,还必须要setnx+过期时间必须同—行。

jifashihan的博客 1332

YOLOv8改进 | 主干篇 | 利用MobileNetV1替换Backbone(轻量化网络结构)

本文给大家带来的改进机制是MobileNetV1,其是专为移动和嵌入式视觉应用设计的轻量化网络结构。这些模型基于简化的架构,并利用深度可分离卷积构建轻量级深度神经网络,其引入了两个简单的全局超参数,用于在延迟和准确性之间进行有效的权衡。实验表明,MobileNets在资源和准确性的权衡方面表现出色,并在多种应用(如对象检测、细粒度分类、面部属性识别和大规模地理定位)中展现了其有效性,这个模型非常适合轻量化的读者来使用。适用检测目标:轻量化网络结构适合轻量化的读者。

Snu77的博客 3966

AI工具 | 每个打工人必备的15款人工智能超级工具

不过,还是有一些靠谱的人工智能平台,它们可不只是营销噱头。有些AI公司正试图改变游戏规则。人工智能工具让人们能够更聪明地工作,而不是更辛苦地劳作。如果你想知道未来有什么,那就来看看这10款人工智能工具吧,它们将彻底改变我们的工作方式。

Vampire_2017的博客 5万+

Redis实现分布式锁

在多线程并发的情况下,我们可以使用锁来保证一个代码块在同一时间内只能由一个线程访问。比如Java的synchronized关键字和Reentrantlock类等等。 这样子可以保证在同一个JVM进程内的多个线程同步执行。 如果在分布式的集群环境中,如何保证不同节点的线程同步执行呢? 怎么才能在分布式系统中,实现不同线程对代码和资源的同步访问? 对于单进程的并发场景,我们可以使用语言...

forever-and-ever的博客 4万+

一、DMSP/OLS、NPP/VIIRS等夜间灯光数据能源碳排放空间化理论介绍

利用DMSP/OLS、NPP/VIIRS等夜间灯光数据开展能源碳排放空间化之前,需要区分与利用夜间灯光数据GDP空间化,两者操作流程并无较大区别,只是GDP空间化选择夜间灯光指数种类有比较多包括总灯光指数、平均灯光指数、综合灯光指数等,但是能源碳排放过程中通常只选择总灯光指数,其次能源碳排放空间化可能对于某些省份工业相对没有那么发达的区域,构建模型时候拟合效果比较差,也就是R方低一些或者显著性差。针对上述拟合度低的情况诸多学者前辈从多个方面开展研究进行提升。

端木宛白的博客家园 4925

手写简单的redis分布式锁

单机版同一个JVM虚拟机内,synchronized或者Lock接口分布式多个不同JVM虚拟机,单机的线程锁机制不再起作用,资源类在不同的服务器之间共享了。

weixin_67154380的博客 1010

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Redis的分布式锁分析

开发同学都知道,在分布式系统中,为了保证多个机器并发操作的数据一致性,常常需要使用分布式锁机制。常用的比如数据库锁,ZK锁,Reis锁等等,今天我们就探讨下Redis分布式锁,说说他的实现原理和应用场景,并介绍如何正确使用分布式锁来解决并发问题

战斧的博客 7297

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring Boot整合Redis实现简单的分布式锁

随着微服务等分布式架构的快速发展及应用,在很多情况下,我们都会遇到在并发情况下多个线程竞争资源的情况,比如我们耳熟能详的秒杀活动,多平台多用户对同一个资源进行操作等场景等。分布式锁的实现方式有很多种,比如基于数据库、Zookeeper、Redis等,本文我们主要介绍Spring Boot整合Redis实现分布式锁。

Ron.Zheng 1万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

简单的redis分布式锁实现

简单的redis分布式锁实现,实现了锁的重入,解决过期问题,误删以及死锁问题

qq_19342829的博客 2846

基于redis手写一个分布式锁

基于redis手写一个分布式锁简介一、分布式锁原理二、java实现redis的分布式锁三、使用redisson实现分布式锁 简介 分布式锁,名字就看的出来是应用于分布式系统中的锁,我们平时熟知的synchronized等一系列锁是在一个jvm内实现的,而很多大型的系统通常都是采用分布式部署开发,不在一个jvm内运行所以synchronized等锁就失效了,分布式锁就是解决分布式系统中锁的问题,下面我们来手写一个基于redis的分布式锁来了解一下分布式锁的原理。本文源码地址:https://github.co

weixin_44032502的博客 799

分布式锁其实很简单,6行代码教你实现redis分布式锁,千万不要再用redisTemplate写redis分布式锁代码实现

分布式锁是一种用于协调分布式系统中多个节点之间对共享资源进行访问控制的机制。它可以确保在分布式环境下,同一时间只有一个节点能够获取到锁,并且其他节点需要等待释放锁后才能获取。以下是使用分布式锁的几个常见场景和原因:避免资源冲突:当多个节点需要同时对共享资源进行读写操作时,使用分布式锁可以确保同一时间只有一个节点能够执行写操作,避免数据冲突和一致性问题。防止重复处理:在某些业务场景中,可能会出现重复处理的问题,例如订单支付、秒杀等。

小小鱼儿小小林的博客 8460

手写一个基于redis的分布式锁

基于redis的分布式锁 一、为什么要做 无疑,关于分布式锁,我们都已比较熟悉,网上有较多的开源解决方案,如redis的redisson,以及zookeeper的curator等,关于这两种分布式锁的使用及原理,后期会写文章介绍。本文主要针对小白,分享一下我学习分布式锁的一些心得,如果是大神请留下您的宝贵意见。 二、俯视代码 关于代码,我写的比较精简,力争在保证功能的情况下让使用上变得更加...

coderyjz的博客 1463

Redis的分布式锁

Redis分布式锁通过Redis原子操作实现互斥访问,核心是SETNX命令设置带过期时间的键值对,配合Lua脚本确保安全释放。Java实现可通过Jedis手动处理锁获取、唯一标识验证和释放逻辑,或使用Redisson简化开发,其提供自动续期、可重入锁等功能。Redlock算法支持多节点部署提高可靠性。注意事项包括合理设置锁超时、确保原子操作、处理时钟漂移等。适用于秒杀、任务调度等需要互斥访问的场景,Jedis适合简单需求,Redisson更适合复杂场景,能显著降低开发复杂度。

Hzx895554135的博客 2708

如何用 Redis 实现一个分布式锁

场景模拟 一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超买,以防止造成不必要的损失是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。 在秒杀系统设计中,超卖是一个经典、常见的问题,任何商品都会有数量上限,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的难点。 针对大量的并发请求,我们可以通过 Redis 来抗,也就是说对于库存

个人站点:javatv.net 2742
上一篇: 《JVM学习》11、执行引擎
下一篇: 整合stripe线上支付收款
pywanggui
码龄1天 6粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

pywanggui

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

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

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

打赏作者

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

抵扣说明:

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

余额充值