从原理到实践,分析 Redisson 分布式锁的实现方案(二)

        上篇讲解了如何用 Redis 实现分布式锁的方案,它提供了简单的原语来实现基于Redis的分布式锁。然而,Redis作为分布式锁的实现方式也存在一些缺点。本文将引入Redisson来实现分布式锁。

一、Redisson是什么

        Redisson是一个基于Redis的分布式Java框架。它提供了丰富的功能和工具,帮助开发者在分布式系统中解决数据共享、并发控制和任务调度等问题。通过使用Redisson,开发者可以轻松地操作Redis的分布式对象(如集合、映射、队列等),实现可靠的分布式锁机制,以及管理和调度分布式环境中的任务和服务。

Redisson提供的功能

  1. 分布式对象:

    • 分布式集合(Set、SortedSet、List)
    • 分布式映射(Map)
    • 分布式队列(Queue、Deque)
    • 分布式锁(Lock)
    • 分布式计数器(AtomicLong)
  2. 分布式限流:

    • 令牌桶算法(Rate Limiter)
    • 漏桶算法(Rate Limiter)
  3. 分布式发布订阅:

    • 发布订阅模式(Pub-Sub)
    • 消息监听器容器(Message Listener Container)
  4. 分布式锁和同步:

    • 可重入锁(ReentrantLock)
    • 公平锁(FairLock)
    • 联锁(MultiLock)
    • 红锁(RedLock)
    • 读写锁(ReadWriteLock)
    • 信号量(Semaphore)
    • 闭锁(CountDownLatch)
    • 栅栏(CyclicBarrier)
  5. 分布式服务和任务调度:

    • 远程服务(Remote Service)
    • 分布式任务调度器(Task Scheduler)
    • 分布式延迟队列(Delayed Queue)
  6. 分布式地理空间索引(Geospatial Index):

    • 地理位置存储
    • 地理位置搜索
  7. 分布式布隆过滤器(Bloom Filter)和可布隆过滤器(Bloom Filter)。

  8. 分布式缓存:

    • 对Redis进行本地缓存
    • Spring缓存注解支持
  9. 分布式连接池:

    • 支持连接池管理和维护
  10. Redis集群和哨兵支持:

    • 支持Redis集群模式
    • 支持Redis哨兵模式
    • 对于使用Redis集群部署的场景,Redisson可以自动识别和操作集群中的多个节点,保证数据的高可用性和扩展性。而对于使用Redis哨兵模式部署的场景,Redisson可以监控并切换到可用的主从节点,实现高可靠性和容错能力。
  11. Spring集成:

    • 与Spring框架的无缝集成
    • 支持Spring缓存注解

二、Redisson分布式锁

Redisson的分布式锁的特点

  1. 线程安全:分布式锁可以确保在多线程和多进程环境下的数据一致性和可靠性。

  2. 可重入性:同一个线程可以多次获取同一个锁,避免死锁的问题。
  3. 锁超时:支持设置锁的有效期,防止锁被长时间占用而导致系统出现问题。
  4. 阻塞式获取锁:当某个线程尝试获取锁时,如果锁已经被其他线程占用,则该线程可以选择等待直到锁释放。
  5. 无阻塞式获取锁:当某个线程尝试获取锁时,如果锁已经被其他线程占用,则该线程不会等待,而是立即返回获取锁失败的信息。  

Redisson的分布式锁的缺点 

  1. 单点故障:Redisson的分布式锁依赖于Redis集群,如果Redis集群出现故障或不可用,可能导致分布式锁的可靠性和可用性受到影响。因此,在使用Redisson分布式锁时,需要特别关注Redis集群的稳定性和高可用性。

  2. 锁竞争:当多个线程同时请求获取分布式锁时,可能出现锁竞争的情况。如果锁竞争较为激烈,可能会导致性能下降和请求超时等问题。此外,由于Redisson分布式锁是基于Redis进行实现的,如果Redis节点的处理能力无法满足高并发的锁请求,可能会导致锁请求被延迟或阻塞。

  3. 死锁风险:分布式环境下,由于网络通信、节点故障等因素,可能导致锁无法正常释放,从而引发死锁问题。需要合理设计和使用锁的超时时间、自动释放机制等来降低死锁风险。

  4. 锁粒度管理:在分布式环境下,锁的粒度管理是一个重要的问题。过于细粒度的锁可能导致并发性能下降,而过于粗粒度的锁可能会影响系统的可伸缩性和并发性能。需要根据具体的业务场景和并发访问模式合理选择锁的粒度。

  5. 数据一致性:使用分布式锁保证多个操作的原子性是很常见的应用场景之一。然而,分布式锁通常只能提供粗粒度的互斥访问,不能保证数据的完全一致性。在一些特定的应用场景中,可能需要额外的措施来确保数据的最终一致性。

Redisson分布式锁源码分析

public interface RLock extends Lock, RLockAsync {
    String getName();

    void lockInterruptibly(long var1, TimeUnit var3) throws InterruptedException;

    boolean tryLock(long var1, long var3, TimeUnit var5) throws InterruptedException;

    void lock(long var1, TimeUnit var3);

    boolean forceUnlock();

    boolean isLocked();

    boolean isHeldByThread(long var1);

    boolean isHeldByCurrentThread();

    int getHoldCount();

    long remainTimeToLive();
}

   RLock接口主要继承了Lock接口,它是Redisson提供的用于分布式锁的核心接口,它定义了获取锁和释放锁等方法 ,并扩展了很多方法。

如:

  • void lock(long leaseTime, TimeUnit unit)

    • 功能:获取锁,并设置锁的自动释放时间。
    • 参数:
      • leaseTime:锁的自动释放时间。
      • unit:时间单位。
  • RFuture<Void> lockAsync(long leaseTime, TimeUnit unit)

    • 功能:异步方式获取锁,并设置锁的自动释放时间。
    • 参数:
      • leaseTime:锁的自动释放时间。
      • unit:时间单位。
    • 返回值:一个RFuture对象,表示异步操作的结果。
  • boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException

    • 功能:尝试在指定的等待时间内获取锁,并设置锁的自动释放时间。
    • 参数:
      • waitTime:等待获取锁的最大时间量。
      • leaseTime:锁的自动释放时间。
      • unit:时间单位。
    • 返回值:如果在等待时间内成功获取锁,则返回true;否则返回false
    • 异常:如果在等待获取锁的过程中被中断,则抛出InterruptedException

        通过上述方法,RLock接口提供了更多对lock()方法的拓展,使得在获取锁时可以设置自动释放时间或进行异步操作。这样可以更加灵活地控制锁的行为,适应不同场景下的需求。

        除了上述拓展,RLock接口还提供了其他方法来支持可重入锁、公平锁、红锁、读写锁等特性,以便满足更为复杂的分布式锁需求。

三、Spring Boot 整合 Redisson 分布式锁 

添加Maven依赖

<!-- Redisson依赖 -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.16.2</version>
</dependency>

<!-- Spring Data Redis依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

 配置Redisson连接application.yml

spring:
  redis:
    cluster:
      nodes:
        - 127.0.0.1:7000
        - 127.0.0.1:7001
        - 127.0.0.1:7002
    password: yourRedisPassword

创建Redisson客户端

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useClusterServers()
                .addNodeAddress(clusterNodes.split(","))
                .setPassword(password);

        return Redisson.create(config);
    }
}

使用分布式锁

        在需要使用分布式锁的地方注入RedissonClient实例,并使用getLock方法创建一个分布式锁对象(RLock)。

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SomeService {

    @Autowired
    private RedissonClient redissonClient;

    public void doSomething() {
        String lockKey = "myLock"; // 锁的key

        RLock lock = redissonClient.getLock(lockKey);
        try {
            lock.lock(); // 获取锁
            // 在这里执行需要加锁保护的代码
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

RLock.lock()

        使用Rlock.lock() 方法时 ,如果当前没有其他线程或进程持有该锁,那么调用线程将立即获得锁定,并继续执行后续的代码。如果其他线程或进程已经持有了该锁,那么调用线程将被阻塞,直到该锁被释放为止。

此外,Rlock.lock() 方法还具有以下特点:

  1. 可重入性:同一个线程可以多次调用 Rlock.lock() 方法而不会造成死锁,只需确保每次 lock() 调用都有相应的 unlock() 调用与之匹配。
  2. 超时机制:可以通过 lock() 方法中的参数设置等待锁的超时时间,避免因为无法获得锁而一直等待。
  3. 自动续期:当线程持有锁的时间超过设置的锁的过期时间时,Redisson 会自动延长锁的有效期,避免因为业务执行时间过长而导致锁过期。
  4. 防止死锁:Redisson 通过唯一标识锁的 ID 来区分不同的锁,防止发生死锁。

lock() 方法加锁流程

RLock.unlock()

   RLock.unlock()方法用于释放由Redission分布式锁所保护的资源。它允许持有锁的线程主动释放锁,从而允许其他线程获取该锁并访问共享资源。

注意事项:

  • RLock.unlock()方法应该在保护的临界区代码执行完毕后进行调用,以确保锁的及时释放。
  • 在多线程环境下,释放锁的顺序应该与获取锁的顺序相对应,以避免死锁或资源争用的问题。
  • 如果当前线程没有持有锁,调用RLock.unlock()方法不会抛出异常,也不会影响其他线程。
  • 如果Redisson客户端刚加锁成功,并且未指定leaseTime,后台会启动一个定时任务watchdog每隔10s检查key,key如果存在就为它⾃动续命到30s;在watchdog定时任务存在的情况下,如果不是主动释放锁,那么key将会⼀直的被watchdog这个定时任务维持加锁。但是如果客户端宕机了,定时任务watchdog也就没了,也就没有锁续约机制了,那么过完30s之后,key会⾃动被删除、key对应的锁也自动被释放了。

unlock()方法解锁流程


四、更多内容

Spring Boot 集成 Redisson分布式锁

从原理到实践,分析 Redis 分布式锁的多种实现方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/45723.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(一)认识InfluxDB

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 1 章 认识InfluxDB 1.1 InfluxDB的使用场景 InfluxDB是一种时序数据库&#xff0c;时序数据库通常被用在监…

day31贪心算法 用最少数量的箭引爆气球 和无重叠区间

题目描述 题目分析&#xff1a; x轴向上射箭&#xff0c;12一支&#xff0c;重叠的需要一支&#xff0c;3-8一支&#xff0c;7-16一支 返回2&#xff1b; 就是让重叠的气球尽量在一起&#xff0c;局部最优&#xff1b;用一支弓箭&#xff0c;全局最优就是最少弓箭&#xff1b…

猿人学第二题—混淆 动态cookie检测

猿人学第二题—混淆 动态cookie检测 1、代码格式化检测2、检测global和navigator.vendorSub3、检测setInterval思考 4、console.log输出检测补环境 简单的document.cookie&#xff0c;location.reload等就不写了 1、代码格式化检测 这里应该是利用了字符串正则匹配性能低的特点…

软考高项(五)信息系统工程 ★重点集萃★

&#x1f451; 个人主页 &#x1f451; &#xff1a;&#x1f61c;&#x1f61c;&#x1f61c;Fish_Vast&#x1f61c;&#x1f61c;&#x1f61c; &#x1f41d; 个人格言 &#x1f41d; &#xff1a;&#x1f9d0;&#x1f9d0;&#x1f9d0;说到做到&#xff0c;言出必行&am…

如何解决创建vue项目后没有webpack.config.js(vue.config.js)文件

◼️ webpack.config.js文件没有的原因 Vue 项目中 vue.config.js 文件就等同于 webpack 的 webpack.config.js。 vue-cli3 之后创建的时候并不会自动创建 vue.config.js&#xff0c;因为这个是个可选项&#xff0c;所以一般都是需要修改 webpack 的时候才会自己创建一个 vue…

什么是PostgreSQL?简要介绍其主要特点和用途

PostgreSQL是一种开源的关系型数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它是最强大和广泛使用的开源数据库之一。PostgreSQL的名称起源于其前身&#xff0c;称为"Ingres"项目&#xff0c;后来被命名为Postgres&#xff0c;而PostgreSQL则是它的进一步…

目录操作在C语言中:一个全面的指南

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

指针进阶(三)

指针进阶&#xff08;三&#xff09; 指针习题组&#xff1a; 01&#xff1a; int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; }运行结果&#xff1a; 原因&#xff1a;这里a是数组名&a…

Linux:centos7:zabbix4.0(安装,监控》Linux》Windows》网络设备)

环境 centos7&#xff08;zabbix服务器&#xff09;内网ip&#xff1a;192.168.254.11 外网ip&#xff1a;192.168.0.188&#xff08;去网络yum源下载&#xff09; centos7&#xff08;被监控端&#xff09;内网ip&#xff1a;192.168.254.33win10&#xff08;被监控端&…

【后端面经】微服务构架 (1-3) | 熔断:抖抖抖不停?微服务熔断策略让你的系统稳如泰山!

文章目录 一、前置知识1、什么是熔断?2、什么是限流?3、什么是降级?4、怎么判断微服务出现了问题?A、指标有哪些?B、阈值如何选择?C、超过阈值之后,要不要持续一段时间才触发熔断?5、服务恢复正常二、面试环节1、面试准备2、面试基本思路三、总结 在微服务构架中…

Java版本工程项目管理系统源码-全面的工程项目管理

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c;…

ADCS知识点全收录! 如何利用证书服务器对域控进行多角度攻击(上)

在2021年的BlackHat大会上&#xff0c;由Will Schroeder和Lee Christensen发布了关于Active Directory Certificate Services 利用白皮书《Certified Pre-Owned - Abusing Active Directory Certificate Services》&#xff0c;其中包含了大量的针对ADCS的攻击手法&#xff0c;…

JavaFx实现自定义窗口

效果 代码 package cn.juhe.zjsb.task;import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Rectangle2D; import javafx.scene.Cursor; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image…

【Nodejs】文件上传

1.初始化准备 1.1 安装依赖 首先创建一个express-multer-upload工程项目&#xff0c;然后在项目中下好各种依赖包。 multer中间件 Multer 是一个 node.js 中间件&#xff0c;用于处理 multipart/form-data 类型的表单数据&#xff0c;它主要用于上传文件。 注意: Multer 不会…

【Ajax】笔记-JQuery发送请求与通用方法

Get请求 语法格式&#xff1a; $.get(url, [data], [callback], [type]) url:请求的 URL 地址。data:请求携带的参数。callback:载入成功时回调函数。type:设置返回内容格式&#xff0c;xml, html, script, json, text, _default。 准备三个按钮分别测试Get 、Post、通用型方…

概率论的学习和整理21:用EXCEL来做假设检验(未完成草稿)

目录 1 EXCEL可以用来做假设检验 1.1 如何打开 数据分析 和 规划求解 1.2 EXCEL里关于正态分布的准备知识 2 基本的假设检验 2.1 最基本的假设检验&#xff0c;单边的Z检验 2.1 双样本F检验 2.1.1 例题 2.1.2 进行F检验之前需要满足一些假设条件 2.1.3 计算步骤 2.1…

Langchain 新手完全指南

原文&#xff1a;Langchain 新手完全指南 Langchain 可能是目前在 AI 领域中最热门的事物之一&#xff0c;仅次于向量数据库。 它是一个框架&#xff0c;用于在大型语言模型上开发应用程序&#xff0c;例如 GPT、LLama、Hugging Face 模型等。 它最初是一个 Python 包&#x…

实战攻防Demo|如何轻松形成自动响应的安全闭环?

从威胁阻断角度来说&#xff0c;拦住黑客的第一步攻击尤为重要。同样&#xff0c;对于攻击者来说&#xff0c;第一步攻击的成本也往往是最高的。日常工作中人们会遇到很多类型的攻击&#xff0c;但暴力破解或者撞库攻击往往被作为黑客的第一步攻击。这主要源于其技术含量低&…

【网络教程】如何快速的解决WordPress“另一更新正在进行”的问题

文章目录 WordPress提示“另一更新正在进行”解决方案手动删除数据库记录使用插件WordPress提示“另一更新正在进行” 当我们在更新WordPress的插件或者升级WordPress时会出现后台提示“另一更新正在进行”,如下图 当我们点击更新后,出现下图提示 出现上述问题是由于在升级Wo…

平板用的触控笔什么牌子好?ipad第三方电容笔推荐

随着技术的发展&#xff0c;出现了各种各样的平板电容笔。一支好的电容笔&#xff0c;不但可以极大地提升我们的工作效率&#xff0c;还可以极大地提升我们的学习效果。平替的电容笔&#xff0c;无论是在技术方面&#xff0c;还是在质量方面&#xff0c;都还有很大的提升空间&a…