java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Springboot redisson实现分布式锁

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

作者:夜空下的星

在实际项目中,某些场景下可能需要使用到分布式锁功能,那么实现分布式锁有多种方式,常见的如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实现分布式锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文