这篇文章主要讲解了“如何使用自定义注解实现redisson分布式锁”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用自定义注解实现redisson分布式锁”吧!

自定义注解实现redisson分布式锁自定义注解

packagecom.example.demo.annotation;importjava.lang.annotation.*;/***desc:自定义redisson分布式锁注解**@author:邢阳*@mail:xydeveloper@126.com*@create2021-05-2816:50*/@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Inheritedpublic@interfaceLock{/***锁的keyspel表达式**@return*/Stringkey();/***持锁时间**@return*/longkeepMills()default20;/***没有获取到锁时,等待时间**@return*/longmaxSleepMills()default30;}aop解析注解

packagecom.example.demo.utils;importcom.example.demo.annotation.Lock;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.reflect.MethodSignature;importorg.redisson.api.RLock;importorg.redisson.api.RedissonClient;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.core.DefaultParameterNameDiscoverer;importorg.springframework.expression.EvaluationContext;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;importorg.springframework.stereotype.Component;importjava.util.Objects;importjava.util.concurrent.TimeUnit;/***desc:解析自定义redisson分布式锁注解**@author:邢阳*@mail:xydeveloper@126.com*@create2021-05-2816:50*/@Aspect@ComponentpublicclassLockAspect{@AutowiredprivateRedissonClientredissonClient;/***用于SpEL表达式解析.*/privatefinalSpelExpressionParserspelExpressionParser=newSpelExpressionParser();/***用于获取方法参数定义名字.*/privatefinalDefaultParameterNameDiscovererdefaultParameterNameDiscoverer=newDefaultParameterNameDiscoverer();@Around("@annotation(com.example.demo.annotation.Lock)")publicObjectaround(ProceedingJoinPointproceedingJoinPoint)throwsThrowable{Objectobject=null;RLocklock=null;try{//获取注解实体信息LocklockEntity=(((MethodSignature)proceedingJoinPoint.getSignature()).getMethod()).getAnnotation(Lock.class);//根据名字获取锁实例lock=redissonClient.getLock(getKeyBySpeL(lockEntity.key(),proceedingJoinPoint));if(Objects.nonNull(lock)){if(lock.tryLock(lockEntity.maxSleepMills(),lockEntity.keepMills(),TimeUnit.SECONDS)){object=proceedingJoinPoint.proceed();}else{thrownewRuntimeException();}}}finally{if(Objects.nonNull(lock)&&lock.isHeldByCurrentThread()){lock.unlock();}}returnobject;}/***获取缓存的key**key定义在注解上,支持SPEL表达式**@return*/publicStringgetKeyBySpeL(Stringspel,ProceedingJoinPointproceedingJoinPoint){MethodSignaturemethodSignature=(MethodSignature)proceedingJoinPoint.getSignature();String[]paramNames=defaultParameterNameDiscoverer.getParameterNames(methodSignature.getMethod());EvaluationContextcontext=newStandardEvaluationContext();Object[]args=proceedingJoinPoint.getArgs();for(inti=0;i<args.length;i++){context.setVariable(paramNames[i],args[i]);}returnString.valueOf(spelExpressionParser.parseExpression(spel).getValue(context));}}service中使用注解加锁使用

/***desc:锁**@author:邢阳*@mail:xydeveloper@126.com*@create2021-05-2817:58*/@ServicepublicclassLockService{@Lock(key="#user.id",keepMills=10,maxSleepMills=15)publicStringlock(Useruser){System.out.println("持锁");return"";}}redisson分布式锁应用

分布式架构一定会用到分布式锁。目前公司使用的基于redis的redisson分布式锁。

应用场景

1.订单修改操作,首先要获取该订单的分布式锁,能取到才能去操作。lockey可以是订单的主键id。

2.库存操作,也要按照客户+仓库+sku维护锁定该库存,进行操作。

代码:

Redisson管理类

publicclassRedissonManager{privatestaticRedissonClientredisson;static{Configconfig=newConfig();config.useSentinelServers().addSentinelAddress("redis://127.0.0.1:26379","redis://127.0.0.1:7301","redis://127.0.0.1:7302").setMasterName("mymaster").setReadMode(ReadMode.SLAVE).setTimeout(10000).setDatabase(0).setPassword("123***");redisson=Redisson.create(config);}/***获取Redisson的实例对象*@return*/publicstaticRedissonClientgetRedisson(){returnredisson;}}分布式锁

importorg.redisson.api.RLock;importorg.redisson.api.RedissonClient;importjava.util.concurrent.TimeUnit;publicclassDistributedLock{privatestaticRedissonClientredissonClient=RedissonManager.getRedisson();publicstaticbooleantryLock(StringlockKey,TimeUnitunit,intwaitTime,intleaseTime){RLocklock=redissonClient.getLock(lockKey);try{returnlock.tryLock(waitTime,leaseTime,unit);}catch(InterruptedExceptione){returnfalse;}}publicstaticvoidunlock(StringlockKey){RLocklock=redissonClient.getLock(lockKey);lock.unlock();}}测试类

publicclassRedissonTest{publicstaticvoidmain(String[]args)throwsException{Thread.sleep(2000L);for(inti=0;i<3;i++){newThread(()->{try{//tryLock,第三个参数是等待时间,5秒内获取不到锁,则直接返回。第四个参数30是30秒后强制释放booleanhasLock=DistributedLock.tryLock("lockKey",TimeUnit.SECONDS,5,30);//获得分布式锁if(hasLock){System.out.println("idea1:"+Thread.currentThread().getName()+"获得了锁");/***由于在DistributedLock.tryLock设置的等待时间是5s,*所以这里如果休眠的小于5秒,这第二个线程能获取到锁,*如果设置的大于5秒,则剩下的线程都不能获取锁。可以分别试试2s,和8s的情况*/Thread.sleep(10000L);DistributedLock.unlock("lockKey");}else{System.out.println("idea1:"+Thread.currentThread().getName()+"无法获取锁");}}catch(Exceptione){e.printStackTrace();}}).start();}}}

我们再打开一个idea,可以把代码复制一份。同事启动两个RedissonTest ,模拟了并发操作。

测试结果:

idea2: Thread-1获得了锁
idea2: Thread-0无法获取锁
idea2: Thread-2无法获取锁


idea1: Thread-2无法获取锁
idea1: Thread-0无法获取锁
idea1: Thread-1无法获取锁

从测试结果发现,最后是只能有一个idea的一个线程能获取到锁。

感谢各位的阅读,以上就是“如何使用自定义注解实现redisson分布式锁”的内容了,经过本文的学习后,相信大家对如何使用自定义注解实现redisson分布式锁这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!