在单体架构中,我们使用synchronize或者Lock就能完成上锁同步的操作,但是这些在分布式,微服务的今天,失去了作用。
分布式锁的实现一般有三种解决方案:
- 基于数据库表实现
- 基于缓存实现,比如redis
- 基于zookeeper实现
那么利用redisson就是基于redis来实现的分布式锁功能。
什么是redisson
从首页的,我们可以大致看出redisson可以实现很多东西,在redisson的基础上,redisson做了超多的封装。
redisson可以完成很多功能,比如缓存各种队列,包括map等这些数据结构,也能完成分布式任务调度,还能完成今天我们说的分布式锁的功能。总之一句话:Redisson是非常强大。
利用redisson完成分布式锁功能
Quick start
我们先看看官网上是如何介绍快速使用redisson。
以上是官网的使用介绍。那么今天以官网的方式来实现我们自己的分布式锁
一,引入maven依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.5</version>
</dependency>
二,创建分布式锁工具类
@Component
public class DistributedLockerUtil {
private RedissonClient redissonClient;
@PostConstruct
private void init() {
if(redissonClient != null){
return;
}
//配置config,如果是单机版的redis,那么就是使用config.useSingleServer()
//如果是集群,那么请使用config.useClusterServers()
Config config = new Config();
config.useSingleServer().setAddress("redis://10.10.100.116:6379");
redissonClient = Redisson.create(config);
}
/**
* 获取RedissonClient
* @return
*/
public RedissonClient getRedissonClient(){
return this.redissonClient;
}
/**
* 加锁
* @return
*/
public void lock(String lockKey){
redissonClient.getLock(lockKey).lock();
}
/**
* 释放锁
*/
public void unLock(String lockKey){
redissonClient.getLock(lockKey).unlock();
}
/**
* 带超时的加锁
* @param lockKey
* @param tomeout 秒为单位
*/
public void lock(String lockKey, Long tomeout){
redissonClient.getLock(lockKey).lock(tomeout, TimeUnit.SECONDS);
}
/**
* 带超市的加锁
* @param lockKey
* @param unit 时间单位
* @param tomeout
*/
public void lock(String lockKey, TimeUnit unit,Long tomeout){
redissonClient.getLock(lockKey).lock(tomeout, unit);
}
/**
* 尝试获取锁
* @param lockKey
* @return
*/
public boolean tryLock(String lockKey){
return redissonClient.getLock(lockKey).tryLock();
}
/**
* 尝试获取锁
* @param lockKey
* @param timeout 尝试等待多少秒时间
* @return
* @throws InterruptedException
*/
public boolean tryLock(String lockKey,Long timeout) throws InterruptedException {
return redissonClient.getLock(lockKey).tryLock(timeout, TimeUnit.SECONDS);
}
/**
*
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待多久时间
* @param leaseTime 上锁后多久释放
* @return
*/
public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) throws InterruptedException {
return redissonClient.getLock(lockKey).tryLock(waitTime,leaseTime,unit);
}
}
创建好之后,就可以使用以上util进行分布式锁的操作
三,新建controller
简单点,我们实现增加库存的业务。每次走进controller增加库存的方法,我们就+1。为了演示效果,其中addStockYaGao方法不加分布式锁,而addStockYaShua加入分布式锁。
@RequestMapping("/stock")
@RestController
public class StockController {
@Autowired
private StockService stockService;
@Autowired
private DistributedLockerUtil distributedLockerUtil;
@GetMapping("/addStockYaGao")
public String addStockYaGao(){
Stock stock = stockService.getOne(1);
stock.setCount(stock.getCount() + 1);
stockService.save(stock);
return "增加牙膏成功";
}
@GetMapping("/addStockYaShua")
public String addStockYaShua(){
try {
distributedLockerUtil.lock("addStock");
Stock stock = stockService.getOne(2);
stock.setCount(stock.getCount() + 1);
stockService.save(stock);
return "增加牙刷成功";
}catch (Exception e){
e.printStackTrace();
return "增加牙刷失败";
}finally {
distributedLockerUtil.unLock("addStock");
}
}
}
四,表数据
原始数据如下:
表对应实体类以及dao,service这里就不贴出来了。
五,JMeter测试效果
测试并发参数:
先对不加锁的addStockYaGao进行测试,
结果:
明显数据不对,300个用户请求,按理来说最后的结果应该是300
再对加锁的addStockYaShua进行测试
结果:
数据正确,更新到了300
总结,使用redisson完成分布式锁功能还是很简单的,大家get得到了吗?
本人水平有限,难免有错误或遗漏之处,望大家指正和谅解,提出宝贵意见,愿与之交流。