为了处理并发产生的问题,我们经常使用到“锁”,将业务执行方法锁起来,避免数据不一致带来的问题。在分布式项目里面则需要使用到分布式锁,而redisssion 则为分布式锁的使用提供了非常便捷的方法。
说明:文中提到的所有代码都上传至我的github项目里面,地址:https://github.com/chenxiangweifeng/study ,(主要在: TestRedissionController 类里面)欢迎加入公众号【Java的docker东风】一起交流,一起成长!
首先写一个业务测试方法进行实验
private void workMethod() throws Exception{
System.out.println("============reidsson 起效果了吗? 可以进入到这个方法吗????=============");
Thread.sleep(2000);
System.out.println("============睡眠结束啦啦啦啦啦啦=============");
}
1)我们首先看不使用锁的多次请求的结果
/**
* 如果不加锁,那么连续请求三次都可以进入这个方法
*/
@ApiOperation(value = "不加锁的情况")
@RequestMapping(value = "/noRedission", method = RequestMethod.POST)
public String testNoRedission() throws Exception{
workMethod();
return "执行成功!";
}
分别请求发起3次请求,result:
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============睡眠结束啦啦啦啦啦啦=============
============睡眠结束啦啦啦啦啦啦=============
============睡眠结束啦啦啦啦啦啦=============
2)接下来我们使用redission 获取锁,然后执行完业务代码之后再次释放锁,这样就能保证在一个方法执行的内部不会有外部的请求插入进来干扰正在执行的业务
/**
* @return
* @date 2020-4-24 Redission分布式锁的使用
* 加锁了也是要执行三次请求的( lock.lock();),只不过暂时未获取到锁的请求处于休眠状态,后续会继续执行的
* 但是每一次请求能保证锁住的内容作为一个整体进行执行。中途不会有新请求插入进来。
*/
@ApiOperation(value = "Redission三行代码基于Redis实现分布式锁的加锁与释放锁")
@RequestMapping(value = "/redission", method = RequestMethod.POST)
public String testRedission() {
RLock lock = redissonClient.getLock(RedisConstantKey.MY_REDISSION_LOCK.key);
lock.lock();
try {
workMethod();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return "执行成功!";
}
运行结果如下:
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============睡眠结束啦啦啦啦啦啦=============
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============睡眠结束啦啦啦啦啦啦=============
============reidsson 起效果了吗?可以进入到这个方法吗????=============
============睡眠结束啦啦啦啦啦啦=============
同一时间请求3次,可以发现业务方法是一个个的执行下来了。后续的请求不会穿插到之前的请求里面。
3)其次我们在同时并发执行时也可以根据业务需求选择让没有获取到锁的请求直接返回不再执行相应的业务方法。
2s内连续点击多次发现方法只执行一次,其他的获取不到锁的请求都被立即返回了。
/**
* lock.tryLock() 这种模式可以实现当请求获取不到锁时直接返回,不必再执行相应业务代码。
*/
@ApiOperation(value = "使用trylock()模式")
@RequestMapping(value = "/redission2", method = RequestMethod.POST)
public String testRedission2() throws Exception {
RLock lock = redissonClient.getLock(RedisConstantKey.MY_REDISSION_LOCK.key);
if(lock.tryLock()){
workMethod();
lock.unlock();
return "执行成功!";
}else {
return "已经有请求在执行,该请求获取不到锁,直接退出!";
}
}
result:
============reidsson 起效果了吗? 可以进入到这个方法吗????=============
============睡眠结束啦啦啦啦啦啦=============