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实现分布式锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring的@Scheduled 如何动态更新cron表达式

    Spring的@Scheduled 如何动态更新cron表达式

    这篇文章主要介绍了Spring的@Scheduled 如何动态更新cron表达式的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • springboot 无法扫描到父类模块中Bean的原因及解决

    springboot 无法扫描到父类模块中Bean的原因及解决

    这篇文章主要介绍了springboot 无法扫描到父类模块中Bean的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • java中使用session监听实现同帐号登录限制、登录人数限制

    java中使用session监听实现同帐号登录限制、登录人数限制

    本文主要介绍了java中使用session监听实现同帐号登录限制、登录人数限制,通过session来监听在线人数和登陆限制,有需要的童鞋可以了解一下。
    2016-10-10
  • MyBatis中foreach标签的collection属性的取值方式

    MyBatis中foreach标签的collection属性的取值方式

    这篇文章主要介绍了MyBatis中foreach标签的collection属性的取值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Spring Boot打包部署和环境配置详解

    Spring Boot打包部署和环境配置详解

    这篇文章主要介绍了Spring Boot打包部署和环境配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Java 实现简单Socket 通信的示例

    Java 实现简单Socket 通信的示例

    这篇文章主要介绍了Java 实现简单Socket 通信的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03
  • SpringBoot Bean被加载时进行控制

    SpringBoot Bean被加载时进行控制

    很多时候我们需要根据不同的条件在容器中加载不同的Bean,或者根据不同的条件来选择是否在容器中加载某个Bean,这就是Bean的加载控制,一般我们可以通过编程式或注解式两种不同的方式来完成Bean的加载控制
    2023-02-02
  • mapper.xml无法解析字段的问题

    mapper.xml无法解析字段的问题

    这篇文章主要介绍了mapper.xml无法解析字段的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • springboot中server.ssl.key-store配置路径的问题小结

    springboot中server.ssl.key-store配置路径的问题小结

    这篇文章主要介绍了springboot中server.ssl.key-store配置路径的问题,文中还记录了Spring Boot SSL(https)实例,介绍在web程序中使用自签名的SSL(HTTPS)证书及创建SSL认证,感兴趣的朋友跟随小编一起看看吧
    2024-02-02
  • springboot打包jar和war包的教程图解

    springboot打包jar和war包的教程图解

    这篇文章主要介绍了springboot打包jar和war包的方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06

最新评论