Springboot使用redisson实现分布式锁的代码示例

 更新时间:2023年06月07日 10:25:12   作者:夜空下的星  
在实际项目中,某些场景下可能需要使用到分布式锁功能,那么实现分布式锁有多种方式,常见的如mysql分布式锁、zookeeper分布式锁、redis分布式锁,本文介绍springboot如何使用redisson实现分布式锁,需要的朋友可以参考下

一、前言

在实际项目中,某些场景下可能需要使用到分布式锁功能,那么实现分布式锁有多种方式,常见的如mysql分布式锁、zookeeper分布式锁、redis分布式锁,从效率上讲,redis无疑是性能最好的,但也会存在一些问题

1.获取锁的线程在执行任务的过程中挂掉,来不及释放锁,这块资源将会永远被锁住(死锁),别的线程再也别想进来,因此我们需要给key加个过期时间,保证这把锁要在一定时间后自动释放。

2.高并发情况下redis分布式锁永久失效 的问题(一个线程可能删除了别的线程的锁)
假设线程 A 可能某些原因执行的很慢很慢,到达过期时间都没执行完,这时候锁过期自动释放,此时线程 B 得到了锁;

随后,线程 A 执行完了任务,线程 A 随之释放锁。但这时候线程 B 还没执行完,线程A实际上 删除的是线程 B加的锁
解决方法:
可以在 释放锁之前做一个判断,验证当前的锁是不是自己加的锁

3.可能出现并发情况
当线程 A 执行的很慢很慢,到达过期时间都没执行完,这时候锁过期自动释放,线程 B得到了锁。此时就有多个线程在访问同步代码块。
解决方法:我们可以使用redisson实现,内部实现锁续期功能。

二、实现

1.在springboot中引入redisson依赖包

 <dependency>
    		<groupId>org.redisson</groupId>
    		<artifactId>redisson-spring-boot-starter</artifactId>
    		<version>3.10.6</version>
		</dependency>

2.配置redisson,代码如下:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
public class RedissonConfig {
	@Bean(destroyMethod = "shutdown")
	public RedissonClient redisson() throws IOException{
		//RedissonClient redisson = Redisson.create(Config.fromYAML(new //ClassPathResource("redisson-single.yml").getInputStream()));
		Config config = new Config();
        config.useSingleServer()
        .setAddress("redis://192.168.6.52:6379").setPassword("123456")
        .setRetryInterval(5000)
        .setTimeout(10000)
        .setConnectTimeout(10000);
        return Redisson.create(config);
   }
}

3.我们以商品库存为例:

import java.util.concurrent.TimeUnit;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.suntree.entity.Price;
import com.suntree.mapper.PriceMapper;
@Service
public class ProductService {
	@Autowired
	RedissonClient redissonClient;
	@Autowired
	ProductMapper productMapper;
	@Transactional
	public String descreaseProduct(String productId,Integer quanlity) {
		String key="des_product_lock:"+productId;
		RLock lock=redissonClient.getLock(key);
		lock.lock();
		Product product =productMapper.selectById(productId);
		if(product ==null) {
			return "产品未找到";
		}
		String result="";
		try {
			if(product .getQuanlity()==0) {
				return "当前数量为0,不能再扣了!!";
			}
			product .setQuanlity(product .getQuanlity()-1);
			productMapper.updateById(product );
			result = "当前数量:" + product .getQuanlity();
			System.err.println(result);
		}catch (Exception e) {
			System.err.println(e.getMessage());
			throw new RuntimeException("扣库存操作失败了");
		}finally {
			lock.unlock();
		}
		return result;
	}
}

这就是实现分布式锁常见场景。

4.接着我们可以在controller层调用,我们可以模拟多线程操作,看扣库存是否会有问题。

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;
import com.suntree.service.ProductService ;
@RestController
@RequestMapping("/product")
public class ProductController {
	@Autowired
	ProductService productService ;
	@GetMapping("/descrease")
	public String descreaseProduct() {
		return productService .descreaseProduct("2020-2020", 200);
	}
}

大家可以自己尝试下。

到此这篇关于Springboot使用redisson实现分布式锁的代码示例的文章就介绍到这了,更多相关Springboot redisson实现分布式锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JAVA 线程通信相关知识汇总

    JAVA 线程通信相关知识汇总

    这篇文章主要介绍了JAVA 线程通信相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • IDEA tomcat启动项目方式

    IDEA tomcat启动项目方式

    这篇文章主要介绍了IDEA tomcat启动项目方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • springmvc前台向后台传值几种方式总结(从简单到复杂)

    springmvc前台向后台传值几种方式总结(从简单到复杂)

    今天小编就为大家分享一篇springmvc前台向后台传值几种方式总结(从简单到复杂),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Java枚举的使用与反射应用方式

    Java枚举的使用与反射应用方式

    枚举类型是一种特殊的类,限定为固定实例集合,且是类型安全和线程安全的,枚举类型不可继承,但可以添加属性和方法,支持单例模式,枚举常量可以通过反射获取和操作,提供了灵活性和扩展性
    2024-09-09
  • Java设计模式之桥接模式详解(Bridge Pattern)

    Java设计模式之桥接模式详解(Bridge Pattern)

    桥接模式是一种结构型设计模式,旨在将抽象部分与其实现部分分离,从而使两者可以独立地变化,桥接模式通过组合关系代替继承关系,将抽象和实现解耦,使代码更具扩展性和维护性
    2025-02-02
  • Java集合的组内平均值的计算方法总结

    Java集合的组内平均值的计算方法总结

    在Java中,经常需要对集合进行各种操作,其中之一就是计算集合的组内平均值,本文将介绍如何使用Java集合来计算组内平均值,并提供一些示例代码和实用技巧
    2024-08-08
  • 堆排序算法的讲解及Java版实现

    堆排序算法的讲解及Java版实现

    这篇文章主要介绍了堆排序算法的讲解及Java版实现,堆排序基于堆这种数据结构,在本文中对堆的概念也有补充介绍,需要的朋友可以参考下
    2016-05-05
  • java中的4种循环方法示例详情

    java中的4种循环方法示例详情

    大家好,本篇文章主要讲的是java中的4种循环方法示例详情,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Java 多线程使用要点分析

    Java 多线程使用要点分析

    这篇文章主要介绍了Java 多线程使用要点分析的相关资料,Java 多线程开发需要主要的细节问题很多,这里就说下,需要的朋友可以参考下
    2016-12-12
  • vue+springboot+webtrc+websocket实现双人音视频通话会议(最新推荐)

    vue+springboot+webtrc+websocket实现双人音视频通话会议(最新推荐)

    这篇文章主要介绍了vue+springboot+webtrc+websocket实现双人音视频通话会议,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-05-05

最新评论