如何正确使用Redisson实现分布式锁

news2024/10/6 1:52:09

分布式锁主要用于保证在分布式系统中,对共享资源的互斥访问,防止多个进程同时操作造成数据不一致。Redis实现分布式锁具备高性能和高可靠性的优势。接下来,我将详细描述如何在Spring Boot项目中使用Redis实现分布式锁。

常见的共享资源举例

1.用户的余额信息
2.商品的库存数量
3.你觉得两个线程同时操作会出问题的字段

依赖配置

首先,在Spring Boot项目中添加Redis相关的依赖。在pom.xml中添加以下内容:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson-spring-boot-starter</artifactId>
        <version>3.15.6</version>
    </dependency>
</dependencies>

在这个示例中,我们使用了Redisson库,这是一个较为成熟的Redis客户端,它在实现分布式锁时提供了简便的API。

Redis 配置

application.ymlapplication.properties文件中配置Redis连接信息:

spring:
  redis:
    host: localhost
    port: 6379

配置Redisson客户端

创建一个配置类,用于初始化Redisson客户端:

import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://localhost:6379");
        return Redisson.create(config);
    }
}

分布式锁实现

创建一个服务类,用于实现分布式锁的逻辑:

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

import java.util.concurrent.TimeUnit;

@Service
public class DistributedLockService {

    @Autowired
    private RedissonClient redissonClient;

    private static final String LOCK_NAME = "distributed-lock";

    // 尝试获取分布式锁
    public boolean acquireLock(long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(LOCK_NAME);
        try {
            // tryLock会在waitTime内等待锁的可用性,获取到锁后会持有它leaseTime时间
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    // 释放分布式锁
    public void releaseLock() {
        RLock lock = redissonClient.getLock(LOCK_NAME);
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

使用示例

创建一个Controller,通过HTTP接口来演示分布式锁的使用:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/lock")
public class LockController {

    @Autowired
    private DistributedLockService lockService;

    @GetMapping("/acquire")
    public String acquireLock() {
        boolean acquired = lockService.acquireLock(10, 20);
        if (acquired) {
            try {
                // 执行业务逻辑,假设需要10秒钟
                Thread.sleep(10000);
                return "Lock acquired and task completed";
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "Task was interrupted";
            } finally {
                // 释放锁
                lockService.releaseLock();
            }
        } else {
            return "Could not acquire lock";
        }
    }
}

测试分布式锁

启动Spring Boot应用,并通过以下命令测试分布式锁:

curl -X GET 'http://localhost:8080/lock/acquire'

通过查看控制台日志和返回结果,可以验证分布式锁的功能。例如,使用不同的客户端同时发送多个请求,只会有一个请求获得锁并完成业务逻辑,其它请求将无法获取锁。

注意点

  1. RedissonClient配置:确保合理配置Redisson客户端,特别是在生产环境下,需要考虑到Reids集群和主从复制的配置。
  2. 锁超时:合理设置锁的等待时间和持有时间,防止死锁和长时间占用资源。
  3. 故障恢复:考虑锁失效或服务重启等异常情况,确保系统能够正确处理这种情况,使锁尽快释放。

小结

通过上述步骤,我们使用Redisson实现了一个简单的分布式锁。在分布式系统中,合理使用Redis提供的分布式锁机制,可以有效防止并发访问共享资源造成的数据不一致问题。Redisson的API简洁而强大,推荐在实际项目中使用。

如果对分布式锁在具体业务中的应用有更多需求,可以进一步研究Redisson提供的多种锁机制,如公平锁和读写锁,以及在复杂场景中的最佳实践。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

27 防火墙不同区域之间是如何通信

26 华三防火墙安全区域-CSDN博客 目标实现不同区域的通信 1 给防火墙配置IP地址 WEB页面配置IP地址 2 在PC机上配置对应对IP地址 &#xff08;该要启用的接口一定要启用 IP地址 子网掩码 网关 一定要查看好&#xff09; 3 将配置好的IP地址对应的不同接口加入到不同的区域上去 …

关于忠诚:忠于自己的良知、理想、信念

关于忠诚&#xff1a; 当我们面对公司、上司、爱人、恋人、合作伙伴还是某件事&#xff0c;会纠结离开还是留下&#xff0c;这里我们要深知忠诚的定义&#xff0c;我们不是忠诚于某个人、某件事、或者某个机构&#xff0c;而是忠诚于自己的良知&#xff0c;忠诚于自己的理想和…

【计算机毕业设计】020基于weixin小程序订餐系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

分班结果老师怎么发给家长?

分班结果老师怎么发给家长&#xff1f; 随着新学期的脚步渐近&#xff0c;老师们的工作也变得愈发繁忙。从准备教学计划到整理课程材料&#xff0c;每一项任务都不容小觑。而其中&#xff0c;分班结果的告知工作&#xff0c;更是让不少老师头疼不已。传统的分班通知方式&#…

【电路笔记】-AB类放大器

AB类放大器 文章目录 AB类放大器1、概述2、AB类放大器介绍3、AB类放大器效率4、偏置方法4.1 电压偏置4.2 分压网络4.3 电位器偏置4.4 二极管偏置5、二极管网络和电流源6、AB类放大器的电源分配7、总结1、概述 A类放大器提供非常好的输出线性度,这意味着可以忠实地再现信号,但…

Linux——进程间通信一(共享内存、管道、systrem V)

一、进程间通信介绍 1.1、进程间通信的概念和意义 进程间通信(IPC interprocess communication)是一组编程接口&#xff0c;让不同进程之间相互传递、交换信息(让不同的进程看到同一份资源) 数据传输:一个进程需要将它的数据发送给另外一个进程 资源共享:多个进程之间共享同样…

webGL可用的14种3D文件格式,但要具体问题具体分析。

hello&#xff0c;我威斯数据&#xff0c;你在网上看到的各种炫酷的3d交互效果&#xff0c;背后都必须有三维文件支撑&#xff0c;就好比你网页的时候&#xff0c;得有设计稿源文件一样。WebGL是一种基于OpenGL ES 2.0标准的3D图形库&#xff0c;可以在网页上实现硬件加速的3D图…

世界人工智能大会中“数据+标注”相关的关键词浅析

标注猿的第79篇原创 一个用数据视角看AI世界的标注猿 大家好&#xff0c;我是AI数据标注猿刘吉&#xff0c;一个用数据视角看AI世界的标注猿。 在国家级数据标注基地建设任务下发后的两个月时间里&#xff0c;全国各地政府、各个高校都快速行动了起来&#xff0c;数据行…

【Linux】压缩命令——gzip,bzip2,xz

1.压缩文件的用途与技术 你是否有过文件太大&#xff0c;导致无法以正常的E-mail方式发送&#xff1f;又或学校、厂商要求使用CD或DVD来做数据归档之用&#xff0c;但是你的单一文件却都比这些传统的一次性存储媒介还要大&#xff0c;那怎么分成多块来刻录&#xff1f;还有&am…

局部静态变量实现的单例存在多个对象

文章目录 背景测试代码运行测试尝试打开编译器优化进一步分析 背景 业务中出现日志打印失效&#xff0c;发现是因为管理日志对象的单例在运行过程中存在了多例的情况。下面通过还原业务场景来分析该问题。 测试代码 /* A.h */ #ifndef CALSS_A #define CALSS_A#include <…

Docker 容器网络及其配置说明

Docker 容器网络及其配置说明 docker容器网络docker的4种网络模式bridge 模式container模式host 模式none 模式应用场景 docker 容器网络配置Linux 内核实现名称空间的创建创建 Network Namespace操作 Network Namespace 转移设备veth pair创建 veth pair实现 Network Namespac…

nature methods | 11种空间转录组学技术的系统性比较

—DOI: 10.1038/s41592-024-02325-3 Systematic comparison of sequencing-based spatial transcriptomic methods 学习了一下空间转录组技术怎么做benchmark&#xff0c;从多个的角度去考虑目前技术的性能&#xff0c;受益良多。但该研究缺少对10X Visium HD的测评&#xff…

mac怎么压缩pdf文件大小,mac压缩pdf文件大小不改变清晰度

在数字化时代&#xff0c;pdf格式因其良好的兼容性和稳定性&#xff0c;成为了文档分享和传输的首选。然而&#xff0c;随着文件内容的丰富&#xff0c;pdf文件的体积也越来越大&#xff0c;给存储和传输带来了不小的困扰。本文将揭秘几种简单有效的pdf文件压缩方法&#xff0c…

python爬虫入门(一)之HTTP请求和响应

一、爬虫的三个步骤&#xff08;要学习的内容&#xff09; 1、获取网页内容 &#xff08;HTTP请求、Requests库&#xff09; 2、解析网页内容 &#xff08;HTML网页结构、Beautiful Soup库&#xff09; 3、存储或分析数据 b站学习链接&#xff1a; 【【Python爬虫】爆肝两…

Vue3基础知识:组合式API中的provide和inject,他们作用是什么?如何使用?以及案例演示

1.provide和inject相较于父子传递的不同在于provide,inject可以用于跨层级通信&#xff08;通俗易懂的讲就是可以实现爷孙之间的直接信息传递&#xff09;。 1.跨层级传递数据 1.在顶层组件通过provide函数提供数据 2.底层组件通过inject函数获取数据 演示一&#xff1a;跨…

vCenter登录失败报500错误:no healthy upstream

过了个周末登录vCenter的时候提示&#xff1a;HTTP状态500 - 内部服务器错误&#xff1b;重启服务后提示&#xff1a;no healthy upstream。如下图&#xff1a; 看到这个情况&#xff0c;肯定就是部分不服务异常了或者压根就没有启动。至于说因为啥异常还不得而知。想着登录管理…

MSPM0G3507——串口0从数据线传输变为IO口传输

默认的跳线帽时这样的&#xff0c;这样时是数据线传输 需要改成这样&#xff0c;即可用IO口进行数据传输

Spring IOC基于XML和注解管理Bean

IoC 是 Inversion of Control 的简写&#xff0c;译为“ 控制反转 ”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出 松耦合、更优良的程序。 Spring 通过 IoC 容器来管理所有 Java 对象…

【国产AI绘图】快手把“可图”大模型开源了,这是一款支持中文的SDXL模型

Kolors 是由 Kuaishou Kolors 团队&#xff08;快手可图&#xff09;开发的基于潜在扩散的大规模文本到图像生成模型。经过数十亿对文本图像的训练&#xff0c;Kolors 在视觉质量、复杂语义的准确性以及中英文字符的文本渲染方面&#xff0c;与开源和专有模型相比都具有显著优势…

【LInux】从动态库的加载深入理解页表机制

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …