Redisson分布式锁学习总结:RedissonRedLock 是如何实现 RedLock 算法的?

redisson实现的MultiLock、RedLock分布式锁使用场景和可能存在的问题。 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它是一个基于Redis实现的高级分布式锁客户端。同时Redisson是Redis官网指定的RedlLock使用Java语言的实现。网络上沿着Redisson的官方文档的介绍已经很多,公平锁、读写锁、信号量、闭锁的用法和源码解析。我这里就不做赘述。本篇博文主要讲使用联锁MultiLock和红锁RedLock的必要场景,以及可能出现的问题。 阅读详情

1、RedLock 算法

1.1、RedLock 算法是什么?

Redis 作者对于分布式锁提出的一种加锁算法,其实核心非常简单:假设redis集群中有N个redis节点,只有当客户端成功在 N/2+1 个实例中成功加锁成功,才算成功持有分布式锁。当然了,这算法里面还有很多其他的小细节,如果大家感兴趣,可以看看 redis 官网关于 RedLock 算法的介绍,是非常详细的。RedLock算法

那么,Redisson 有对应的实现么?

那是必须有的,各种锁都提供了,难道还会缺这个么?同时,我们可以在官网看到,官网对于 RedLock 算法的Java客户端实现,首推 Redisson。
在这里插入图片描述

1.2、为什么需要 RedLock 算法?

回头想想,为什么需要 RedLock 算法?

我们知道,之前提到的分布式锁有:可重入锁、公平锁、读写锁,他们其实底层都是根据key计算出一个槽(slot),这个槽可以对应到某个 Redis 集群的一个节点;那么就是说,这些分布式锁仅仅是在一个节点上加锁,那么下面的情况就会出现不同客户端持有锁:

  • Redis 集群是多主多从架构,假设客户端1在MasterNode1上成功持有锁[myLock],但不幸的是,MasterNode1突然宕机了,并且此时还未将数据完全同步给SlaveNode1(包括客户端1的加锁信息),那么当 SlaveNode1 被选举为新的 MasterNode1 后,其他客户端就可以在新的 MasterNode1成功持有锁[myLock]。

其实这个场景,redis 官网在介绍 RedLock 算法的时候也提到了~
在这里插入图片描述

正是因为可能出现上面的场景,导致不同客户端可同时持有同一把锁,所以才推出 RedLock 算法。

但是我们上篇文章不是介绍了可以同时持有N个资源的 RedissonMultiLock 么,感觉它的实现原理可以完成这个 RedLock 算法。确实,在 Redisson 中,RedissonRedLock 就是基于 RedissonMultiLock 上面做的扩展,并且仅仅重写了三方法,下面我们将简单介绍一下。

2、RedissonRedLock

2.1、使用demo:

public class RedissonRedLockDemo {

    public static void main(String[] args) {
        RedissonClient redissonClient = RedissonClientUtil.getClient("");
        RLock rLock1 = redissonClient.getLock("lock1");
        RLock rLock2 = redissonClient.getLock("lock2");
        RLock rLock3 = redissonClient.getLock("lock3");
        RedissonRedLock redLock = new RedissonRedLock(rLock1, rLock2, rLock3);
        redLock.lock();
        redLock.unlock();

        int result1 = CRC16.crc16("lock1".getBytes()) % 16384;
        int result2 = CRC16.crc16("lock2".getBytes()) % 16384;
        int result3 = CRC16.crc16("lock3".getBytes()) % 16384;
        System.out.println("========测试一=========");
        System.out.println(result1);
        System.out.println(result2);
        System.out.println(result3);

        int result11 = CRC16.crc16("lockone".getBytes()) % 16384;
        int result21 = CRC16.crc16("locktwo".getBytes()) % 16384;
        int result31 = CRC16.crc16("lockthree".getBytes()) % 16384;
        System.out.println("========测试二=========");
        System.out.println(result11);
        System.out.println(result21);
        System.out.println(result31);

        System.out.println("redis cluster 三个节点,平均 slot:"+16384/3);
    }

}

我们可以看到,RedissonRedLock 不愧是基于 RedissonMultiLock 做的简单扩展,确实连使用都是基本一致的;只需要配置好 N 个锁,一般数量就是对应集群中主节点的数量,然后创建一个 RedissonRedLock 对象,接着就是调用获取锁和释放锁的方法即可。

2.2、使用 RedissonRedLock 时需要注意 key 的使用

那下面的那些计算slot是怎么回事?

在 RedLock 算法中提到的是,获取锁其实就是在所有 Rediss 实例节点使用同一个 key 进行加锁操作。

但在 Redisson 中,执行lua脚本前是需要根据 Key 来定位 slot 的,然后 slot 能对应一个 Redis 节点。那么,如果我们在使用 RedissonRedLock 时,如果所有 RLock 都指定同一个key,都等同于当前客户端在重复获取同一把锁,那么最终就达不到 RedLock 算法的效果了。

那么应该怎么指定 RedissonRedLock 中锁的 key 呢?

我们先看一下上面关于slot计算的两个测试结果:

========测试一=========
11346
7217
3088
========测试二=========
10453
998
6216

redis cluster 三个节点,平均 slot:5461

Process finished with exit code 0

redis 集群中,slot 的总数为 16394,如果集群中有三个主节点,那么第一个主节点的slot槽有:[1,5461]、第二个主节点的slot槽有:[5462,10923]、第三个主节点的slot槽有:[10924,16384]。当然了,不一定就是这些数,但是大概也差不了多少了。

我们可以发现,测试一中的key都分别分布在三个节点中了,而测试二中的key,一个在节点1中,两个在节点2中;这么一看,明显测试一中的key使用更符合 RedLock 算法。那么,我们可以认为测试一的key在RedissonRedLock 中使用是符合 RedLock 算法的。

其实,想保证 key 一定是使用正确的话,最稳健的就是研究 CRC16 算法是如何利用 key 定位 slot 的,当你分析透彻了,怎么使用也不在话下了。

2.3、源码分析:

好了,上面关于 key 在 RedissonRedLock 应该如何使用,也简单地分析完了,下面继续 RedissonRedLock 的源码分析。

因为 RedissonRedLock 是基于 RedissonMultiLock 做的简单扩展,而且只是重写了三方法,那么源码是非常的简单的,我们直接上源码。

RedissonRedLock 源码:

public class RedissonRedLock extends RedissonMultiLock {

    /**
     * Creates instance with multiple {@link RLock} objects.
     * Each RLock object could be created by own Redisson instance.
     *
     * @param locks - array of locks
     */
    public RedissonRedLock(RLock... locks) {
        super(locks);
    }

    @Override
    protected int failedLocksLimit() {
        return locks.size() - minLocksAmount(locks);
    }
    
    protected int minLocksAmount(final List<RLock> locks) {
        return locks.size()/2 + 1;
    }

    @Override
    protected long calcLockWaitTime(long remainTime) {
        return Math.max(remainTime / locks.size(), 1);
    }
    
    @Override
    public void unlock() {
        unlockInner(locks);
    }

}

重写failedLocksLimit():

重写这个方法是因为,在 RedissonMultiLock 中,是要保证所有子锁都获取成功,连锁才算获取成功,所以 RedissonMultiLock 的 failedLocksLimit() 方法返回的是0。

而 RedissonRedLock 重写后,失败上限就是locks.size()/2 + 1,即 RedLock 算法中,大多数节点成功获取锁即可。

重写calcLockWaitTime(long remainTime):

RedissonMultiLock 遍历锁列表获取锁时,每个锁调用 tryLock 的等待时间都是同样的,即[baseTime/2,baseTime]之间的随机数。其中 baseWaitTime = locks.size() * 1500。因为 RedissonMultiLock 的 calcLockWaitTime 方法就是传入什么返回什么。

而 RedissonRedLock 重写后,是每个锁平分这个等待时间,如果均分后小于1,那就是1。我觉得这个重写,最大的意义在于能快速到下一个redis节点获取锁,因为 RedLock 算法只需保证大多数节点成功获取锁即可,避免等待多余的时间。

重写unlock():

直接调用 RedissonMultiLock 的 unlockInner() 方法。

3、最后

到此,关于 RedissonRedLock 锁的分析就完毕了;但其实 RedLock 算法不只这么一点东西,如果大家对这个算法感兴趣,可以到官网上面看看作者的介绍哈~

大家如果对此系列的文章感兴趣的话,可以直接关注专栏:<<分布式锁系列文章>>

Redis7高级之Redlock算法和Redisson的使用(十) 该方案为了解决数据不一致的问题,直接舍弃了异步复制只使用 master 节点,同时由于舍弃了 slave,为了保证可用性,引入了 N 个节点,官方建议是 5。设置了maxmemory的选项,假如redis 内存使用达到上限,没有加上过期时间就会导致数据写满 maxmemory,这就需要内存淘汰策略。​ 加入在集群环境中,redis失败2台,可接受。2N+2 = 2 * 2+2 =6,部署6台。2N+2= 2 * 1+2 =4,部署4台。N = 2X + 1 (N是最终部署机器数,X是容错机器数) 阅读详情

相关推荐

面试专栏:Redisson和RedLock实现分布式锁

底层原理:加锁解锁步骤:Redisson的“看门狗”(Watchdog)机制是指在Redisson的分布式锁实现中,用于防止客户端在持有锁的过程中由于各种原因(如崩溃或网络问题)而无法正常释放锁,导致其他客户端无法获取锁的情况。自动续租:故障检测:默认行为:底层原理:加锁解锁步骤:RedLock算法本身并不提供内置的“看门狗”机制。RedLock的主要策略是在多个独立的Redis实例上实现锁,以提高容错性和安全性。在RedLock算法中,客户端负责锁的获取和释放,以及处理锁的续租。 总体来说,Redisso

weixin_62827806的博客 894

分布式锁 Redisson Redlock

java分布式锁

gb4215287的博客 2033

Redisson分布式锁学习总结:RedissonMultiLock 如何同时锁住N个资源

Redisson分布式锁学习总结:RedissonMultiLock 如何同时锁住多个资源

Howinfun的博客 6585

RedLock & Redisson分布式锁

Redisson&RedLock

爱吃榴莲的小白 6549

Redisson分布式锁原理、实战与避坑指南:从秒杀到缓存击穿的完整解决方案

在分布式系统和微服务架构中,并发控制是保障数据一致性的核心技术挑战。其核心原理在于通过一个全局可见的协调服务(如Redis),实现跨进程、跨服务的互斥访问,从而解决多节点同时操作共享资源引发的数据竞争问题。这项技术的核心价值在于为分布式环境提供了类似单机线程锁的同步能力,是构建高可靠、强一致性系统的基石。其典型应用场景广泛,包括防止电商秒杀中的库存超卖、确保分布式任务调度的幂等性、以及应对缓存击穿时对数据库的并发查询保护。本文以Java生态中广泛使用的Redisson客户端为例,深入剖析其基于Redis H

Eric.Net的专栏 363

Redis分布式锁实现与Redisson最佳实践

分布式锁是确保分布式系统中共享资源互斥访问的核心技术,其核心原理是通过中央存储系统(如Redis)实现锁状态的原子性操作。在技术实现上,需要解决互斥性、防死锁、容错性等技术挑战。Redis的SETNX命令虽然能实现基础分布式锁,但在生产环境中面临锁续期、误删除等问题。Redisson作为Java生态的Redis客户端,提供了自动续期、可重入锁等工业级解决方案,特别适合电商库存扣减、金融交易等高并发场景。通过比较SETNX方案与Redisson的性能表现,后者在锁等待和网络抖动场景下表现更优,是分布式系统实现

weixin_34060299的博客 177

如何快速掌握Redisson分布式锁:RedLock算法的完整Java实现指南

Redisson分布式锁是Java开发者在微服务架构中实现高可用分布式锁的最佳选择。作为基于Redis的Java客户端,Redisson提供了完整的RedLock算法实现,确保在分布式环境下的数据一致性和线程安全。💪 ## 🚀 Redisson分布式锁的核心优势 Redisson不仅仅是Redis的Java客户端,更是一个功能丰富的分布式服务框架。它的分布式锁实现具备以下独特优势: -

gitblog_01162的博客 777

英飞凌IGBT驱动芯片2ED020I12F2去饱和电路设计总结整理收集

记录下英飞凌IGBT驱动芯片限流电阻阻值设计

nizhenyuchina的博客 5996

Rydr抢单分布式锁实战:Redis、MySQL、Redisson、RedLock五种方案深度对比

**Rydr** 是一个基于 **Spring Cloud 微服务**构建的完整网约车平台,其中最经典的并发场景就是**司机抢单**:一个订单推送出去后,成百上千个司机同时点击"抢单",如何保证**一单只被一个司机抢走**?这正是**分布式锁**要解决的核心问题。本项目在订单服务中直接实现了 5 种抢单方案:**无锁、JVM 锁、MySQL 锁、Redis 锁、Redisson 锁 + RedLo

gitblog_01032的博客 393

总结:知识图谱KG+大模型LLM

知识图谱KG+大模型LLM

安静的软件工程师 4210

RV1126开发板性能实测:网络、温度与功耗全解析

本文对RV1126开发板进行了全面的性能实测,重点分析了网络性能、温度表现与功耗特性。测试发现UDP带宽可达500Mbps,但TCP性能受限于协议栈;散热设计对持续性能至关重要,大板子在AI推理和视频推流中表现更稳定。为嵌入式开发者提供了真实的选型参考和优化建议。

d3e4f的博客 267

Redisson分布式锁源码解读

目录Redisson源码分析Redis 发布订阅加锁tryLocklock解锁unlock()RedLock 上篇文章写了Redis分布式锁的原理和缺陷,过程中提到了Redisson这个框架,Redisson具体是什么呢? Redisson的源码解读工作量还是挺大的,其中用到了大量的Java并发类,并且引用了Netty作为通信工具,实现与Redis组件的远程调用,这些知识点如果要全部讲解的话不太现实,本文的重点主要是关于Redisson分布式锁的实现原理,所以网络通信和并发原理这块不会太仔细。 Redi

QiuHaoqian的博客 805

浮点数运算的陷阱与启示:FP16加法器/乘法器开发中的常见误区

本文深入探讨FP16加法器和乘法器开发中的常见误区,包括FP16格式解析、阶码对齐陷阱、尾数运算风险及规格化处理。通过Verilog实战代码展示防御性编程技巧,帮助开发者避免边界条件处理和异常状态管理中的错误,提升硬件设计的可靠性和效率。

dell8的博客 250

【07期】Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式: 数据库乐观锁; 基于Redis的分布式锁; 基于ZooKeeper的分布式锁。 本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。 要点 Redis要实现分布式锁,以下条件应该得到满足 互斥性 在任意时刻,只有一个客户端能持有锁。 不能死锁 客户端在持有锁的期间崩溃而没有主动解锁,也能保证后...

Java笔记虾 5548

【Ranger】mac下Apache Ranger编译安装

a、编译过程中出现测试用例不通过和文件认证错误错误:带上参数-DskipTests=true -Drat.skip=true 重新编译;b、若编译过程中出现缺少jar包的情况,可能下载不了,需要手动自动添加;c、编译所需的其他工具如maven等安装配置略。采用这个会报错,因此我才用了下面一个命令。初始化设置Ranger Admin:执行。然后进入target目录。

九师兄 2104

Oracle EBS与SAP数据数据切换至迁移华为MetaERP分析

Oracle EBS到华为MetaERP的数据迁移可采用“表对表复制”思路,因其模块化设计下数据模型标准化、边界清晰。核心业务对象存储在结构明确的主表中,与MetaERP模型兼容度高,便于直接映射。而SAP到MetaERP的迁移则因SAP高度优化的复杂表结构(如簇表/池表)、数据分散冗余、深度依赖配置等特点,无法简单复制,必须采用基于业务对象的迁移方法,通过视图/BAPI提取数据并进行深度转换。两种迁移的本质差异源于源系统的数据模型设计理念不同。

金牌架构师 1379

Redis分布式锁-这一篇全了解(Redission实现分布式锁完美方案)

在某些场景中,多个进程必须以互斥的方式独占共享资源,这时用分布式锁是最直接有效的。随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点),在有些场景中,为了保证数据不重复,要求在同一时刻,同一任务只在一个节点上运行,即保证某一方法同一时刻只能被一个线程执行。

C18298182575的博客 808

第6章: MMU Notifier在KVM虚拟化中的应用

本文分析了KVM如何利用MMU Notifier机制维护客户机与宿主机地址映射一致性。KVM采用三层地址空间转换架构(GVA→GPA→HPA),通过硬件辅助虚拟化(EPT/NPT)实现高效转换。重点探讨了KVM MMU Notifier回调实现,包括invalidate_range_start/end等核心函数,以及HVA范围处理流程。当宿主机内存变化时,KVM通过注册的notifier回调及时更新映射关系,确保虚拟化环境的内存一致性。文章详细解析了相关数据结构和关键代码实现,揭示了KVM内存管理的核心机制

图形/计算GPU的驱动与虚拟化技术分享园地 2324

Redis分布式锁

在某些场景中,多个进程必须以互斥的方式独占共享资源,这时用分布式锁是最直接有效的。随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点),在有些场景中,为了保证数据不重复,要求在同一时刻,同一任务只在一个节点上运行,即保证某一方法同一时刻只能被一个线程执行。

我的博客 825

【C++项目】从零实现RPC框架「三」:项⽬抽象层实现

本文详细介绍了如何从零实现一个 C++ RPC(远程过程调用)框架,包括通信抽象、消息抽象、通信实现、以及消息分发器的实现。通过系统化的代码示例,展示了如何构建一个高效、灵活且可扩展的 RPC 框架。

You build it, you run it 2162

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Redis应用详解(一)分布式锁

1. 前言 在某些场景中,多个进程必须以互斥的方式独占共享资源,这时用分布式锁是最直接有效的。 随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点),在有些场景中,为了保证数据不重复,要求在同一时刻,同一任务只在一个节点上运行,即保证某一方法同一时刻只能被一个线程执行。在单机环境中,应用是在同一进程下的,只需要保证单进程多线程环境中的线程安全性,通过 JAVA 提供的 volatile、ReentrantLock、synchronized 以及 concurre

傅红雪的专栏 4649

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

分布式锁从原理到实践:Redis、ZooKeeper等实现与避坑指南

在微服务与集群部署环境中,多个进程对共享资源的并发访问需要跨节点的互斥机制,这就是分布式锁要解决的核心问题。合格的分布式锁必须满足互斥性、防死锁、可重入等基本要求,而不同实现方案各有优劣。Redis通过SET NX EX原子命令实现高性能加锁,配合Lua脚本保证解锁安全,Redisson的看门狗机制还能自动续期;ZooKeeper则利用临时顺序节点提供公平锁,并通过监听前驱节点规避羊群效应;etcd结合租约与Revision实现强一致锁。实际生产中还常遇到锁超时、误删他人锁、主从切换丢锁等典型问题,本文梳理

weixin_33841503的博客 381

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Redisson分布式锁与高级特性实战:从原理到生产环境调优

分布式系统开发中,分布式锁是保障数据一致性的核心技术之一,其核心原理是通过协调多个节点对共享资源的访问,避免并发冲突。在Java生态中,Redisson作为基于Redis的分布式服务工具箱,不仅实现了高效的分布式锁,还通过其独特的“看门狗”机制解决了锁的自动续期问题,有效防止了死锁和任务未完成锁已释放的难题。这一机制显著提升了分布式系统的可靠性与稳定性。在技术价值层面,Redisson将Redis从单纯的数据存储扩展为分布式协调服务,为微服务架构下的限流、缓存、分布式集合等场景提供了开箱即用的解决方案。其高

weixin_30613343的博客 402

从SETNX到Redisson:分布式锁演进与踩坑实战解析

分布式锁是微服务架构中保证多节点互斥访问的关键机制。基于Redis的分布式锁因其高性能和原子操作被广泛应用,但简单的SETNX命令在工程实践中面临锁失效、误删、死锁等问题。本文深入解析分布式锁的核心原理,从Redis命令的原子性、过期时间设置到Lua脚本保证解锁原子性,逐步梳理技术演进过程。同时介绍Redisson框架如何通过看门狗机制、可重入锁等特性解决复杂场景下的锁管理难题。适用于订单防重、定时任务互斥、缓存并发控制等典型应用,帮助后端开发深入理解分布式锁的选型与最佳实践。全文以工程实践视角,完整呈现从

weixin_33851177的博客 321
上一篇: Redisson分布式锁学习总结:RedissonMultiLock 如何同时锁住N个资源
下一篇: 并发编程 之 CAS
Howinfun
博客等级 码龄10年 165粉丝 213原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值