(11)Redis------分布式锁的实现方式之一(基于Springboot项目搭建)
Redis锁由来
首先我们说一下分布式出现之前的锁
进程锁:
控制某一系统中多个进程访问共享资源时候造成冲突,因为单个进程是有独立性的,进程与进程之间无法访问其他进程的资源,因此线程锁实现方式synchronized等无法完成。
线程锁:
线程锁是主要是给某一代码块加锁,当这个代码块加锁后,比如synchronized后,第二个线程进来就无法执行这一段代码。常用的还有给某一个全局变量加锁,因为全局变量如果不加锁的话,一旦多个线程进来,并发的情况下,这个变量的值就会造成混乱。常用的有threadLocal修饰全局变量。
随着分布式部署的出现,越来越多的问题开始涌现,比如之前的那些锁的问题,已经不再满足现在多个系统互相调用时候出现的变量共享了,这时候,分布式锁就应运而生。
这一节我们主要讲一下redis分布式锁,当然了分布式锁常用的还有zookeeper分布式锁,以后我们再讨论zk锁。
Redis分布式锁具体实现:
1. 引入jar包,maven依赖如下
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.1.0</version>
</dependency>
2. Java类
/*** 基于redisson的实现的redis分布式锁* com.bjrhxq.platform.application.distributedlock.redis**/
public class RedisDistributedLock {private final static Logger logger = LoggerFactory.getLogger(RedisDistributedLock.class);/*** 加锁等待时间*/private Long lockWaitTime;/***自动解锁时间*/private Long autoReLockTime;/*** 时间单位 1 秒,2 分钟,3小时,4天*/private Integer timeUnit;/*** rediss客户端*/private RedissonClient redissonClient;private final static Long LOCKWAITTIME_NUM = 0L;//默认加锁等待时间(0秒)private final static Long AUTORELOCKTIME_NUM = 5L;//默认释放锁时间(5秒)private final static Integer TIMEUNIT_VALUE = 1;//单位默认值(秒)private RedisDistributedLock(){}public RedisDistributedLock(String redisServices,Long _lockWaitTime,Long _autoReLockTime){if (StringUtils.isBlank(redisServices)){logger.error("redisServices为空!请上传");throw new BzException("redisServices为空");}this.autoReLockTime = _autoReLockTime == null?AUTORELOCKTIME_NUM:_autoReLockTime;this.lockWaitTime = _lockWaitTime == null?LOCKWAITTIME_NUM:_lockWaitTime;this.timeUnit =TIMEUNIT_VALUE;redissonClient = RedissonUtils.getInstance().getRedisson(redisServices);}public RedisDistributedLock(String redisServices,Long _lockWaitTime,Long _autoReLockTime,Integer _timeUnit){if (StringUtils.isBlank(redisServices)){logger.error("redisServices为空!请上传");throw new BzException("redisServices为空");}this.autoReLockTime = _autoReLockTime == null?AUTORELOCKTIME_NUM:_autoReLockTime;this.lockWaitTime = _lockWaitTime == null?LOCKWAITTIME_NUM:_lockWaitTime;this.timeUnit =_timeUnit;redissonClient = RedissonUtils.getInstance().getRedisson(redisServices);}//程序一旦启用不能关闭redissonClient否则会报cannot be started once stopped 导致程序中断无法启动,该方法只用于测试使用关闭客户端与服务端连接public void closeReddisson(){redissonClient.shutdown();}/*** 获取锁* @param lockName*/public boolean getLock(String lockName){RLock rlock = redissonClient.getLock(lockName);try {return rlock.tryLock(lockWaitTime,autoReLockTime,exchangeTimeUnit(timeUnit));} catch (InterruptedException e) {return false;}}/*** 释放锁* @param lockName*/public void releaseLock(String lockName){RLock rlock = redissonClient.getLock(lockName);rlock.unlock();}private TimeUnit exchangeTimeUnit(int _timeUnit){switch (_timeUnit) {case 1:return TimeUnit.SECONDS;case 2:return TimeUnit.MINUTES;case 3:return TimeUnit.HOURS;case 4:return TimeUnit.DAYS;}return TimeUnit.SECONDS;}
}
3. 测试类
/*** src.test**/
public class TestRedissionShan {final String LOCK_KEY="TEST_123";public static void main(String[] args) {TestRedissionShan test1 = new TestRedissionShan();test1.testLock("test1");TestRedissionShan test2 = new TestRedissionShan();test2.testLock("test2");}public void testLock(String name){
//下面的三个地址以及端口可以参照上一篇文章redis集群,写入你配好的集群地址RedisDistributedLock redisDistributedLock = new RedisDistributedLock("192.168.122.32:9210,192.168.122.33:9211,192.168.122.34:9212",null,5L,1);
//第二个测试再将此段代码解除注释
// if ("test2".equals(name)){
// try {
// System.err.println(name+"准备睡眠6秒");
// Thread.sleep(6000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }boolean lock = redisDistributedLock.getLock(LOCK_KEY);System.out.println(name+"拿到锁了吗?"+lock+"---线程名字:"+Thread.currentThread().getName());if (lock){System.out.println(name+"拿到锁了准备操作。。。。。");System.out.println(name+"我自己测试还能不能加锁<"+redisDistributedLock.getLock(LOCK_KEY)+">");}else{System.err.println(name+"未拿到锁不操作。。。。。");}}}
测试结果:
est1拿到锁了吗?true---线程名字:main
test1拿到锁了准备操作。。。。。
test1我自己测试还能不能加锁<true>
test2拿到锁了吗?false---线程名字:main
test2未拿到锁不操作。。。。。
可见在test1拿到锁后,如果不释放,test2是没有办法对这个锁进行任何操作的
下面我们再测试下,将上面的那一段注掉的代码释放开(因为默认释放时间是5秒)
我们让test2线程等待6秒,正常情况下是可以再次对同一个锁进行操作的,因为test1过了5秒已经释放了锁
接下来看输出结果:
est1拿到锁了吗?true---线程名字:main
test1拿到锁了准备操作。。。。。
test1我自己测试还能不能加锁<true>
test2准备睡眠6秒
test2拿到锁了吗?true---线程名字:main
test2拿到锁了准备操作。。。。。
test2我自己测试还能不能加锁<true>
测试结果正如前面所说,这里需要注意下有个当前线程加完锁后,还可以对其进行加锁,我们不妨想一下,你自己加的锁,加完后你自己可以对其做任何操作,包括再次加锁(再次加锁我们只是测试,实际中并不会使用)
以上就是Redis分布式锁的一个实现方式,当然了,redis还有很多种实现方式,原生的不容易理解,这里我们选择了一种相对容易上手的。
(11)Redis------分布式锁的实现方式之一(基于Springboot项目搭建)相关推荐
- redis 分布式锁的实现方式
情景如下: 我们有一批任务需要由多个分布式线程处理,每个任务都有一个taskId,为了保证每个任务只被执行一次,在工作线程执行任务之前,先获取该任务的锁,锁的key可以为taskId 方式1:set( ...
- Java版基于Redis分布式锁的实现方式
一.什么是分布式锁? 要介绍分布式锁,首先要提到分布式锁相对应的线程锁和进程锁, 线程锁:组要是给方法.代码块加锁,当方法或者代码块使用锁时,在同一时刻只有一个线程可以执行该方法或者代码块,线程锁只在 ...
- Redis分布式锁 Spring Schedule实现任务调度
一看到标题就知道,这一篇博客又是总结分布式工作环境中集群产生的问题,个人觉得分布式没有那么难以理解,可能也是自己见识比较浅,对我来说,分布式只是一种后端业务演进时的一种工作方式,而真正实现这种工作方式 ...
- redis setnx 分布式锁_手写Redis分布式锁
分布式锁使用场景 现在的系统都是集群部署,每个服务都不是单节点的了.比如库存服务,可能部署到3台机器上分别命名为节点1,节点2,节点3.库存服务需要扣减库存,扣减库存肯定需要锁吧,如果使用Lock或者 ...
- getset原子性 redis_一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)
各个版本的Redis分布式锁 V1.0 V1.1 基于[GETSET] V2.0 基于[SETNX] V3.0 V3.1 分布式Redis锁:Redlock 总结 <Netty 实现原理与源码解 ...
- 一个项目部署多个节点会导致锁失效么_一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)...
各个版本的Redis分布式锁 V1.0 V1.1 基于[GETSET] V2.0 基于[SETNX] V3.0 V3.1 分布式Redis锁:Redlock 总结 <Netty 实现原理与源码解 ...
- 探讨Redis分布式锁解决优惠券拼抢问题
一.什么是分布式锁 分布式锁是控制不同系统之间访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来确保数据一致性. 二.为什么需要分布式锁 ...
- 说一说redis分布式锁的几种实现及优缺点
基于Jedis setnx.expire实现分布式锁(存在问题,作为错误示范) 先引入相关依赖(jedis 2.3.0后支持redis集群模式,2.4.2后支持jedisCluster多线程处理,2. ...
- 得物技术浅谈深入浅出的Redis分布式锁
一.什么是分布式锁 1.1 分布式锁介绍 分布式锁是控制不同系统之间访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性. 1.2 ...
- Redis分布式锁一文全攻略
分布式锁概念 分布式锁其实就是,控制分布式系统的不同进程共同访问共享资源的一种锁的实现.如果不同系统或同一个系统的不同主机去访问一个共享的临界资源,往往需要互斥来防止彼此干扰,以保证一致性. 分布式锁 ...
最新文章
- 比较ArrayList、LinkedList、Vector
- GitHub发福利:30多万元资源,学生可以免费用
- 织女的红线_JAVA
- emacs-w3m查看html帮助手册
- 英特尔+性能+linux,Linux 4.20内核在英特尔处理器上性能比Linux 4.19低,附原因解释...
- urlconnection.connect()和url.openconnection()的区别
- Exchange2007获取OWA邮箱容量的代码
- Android 四大组件学习之Service六
- python与财务报表分析_《财务报表分析》第八章 企业财务综合分析与业绩评价课后练习...
- 分享免费的主流电商平台商品图片批量下载方法
- 字节跳动的产品经理是怎么工作的?
- 胸怀——勇气——智慧
- 正则表达式生成器,测试器(附C#代码)
- WCF各种banding支持的类型
- class和Class的区别
- 这是不是你在找的【电销帮手】——人机耦合佳信静默机器人
- java之ResourceBundle类详细分析(全)
- 韩信点兵问题的c++解法【笔记】
- pvs-stdio ue4_使用PVS-Studio for C#在GitLab中分析合并请求
- windows终端连接虚拟机