Springboot实现分布式锁(Spring Integration+Redis)
一.在项目的pom.xml中添加相关依赖
1)Spring Integration依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency>
2)Spring Integration Redis依赖
<dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-redis</artifactId> </dependency>
3)Spring Data Redis依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
application.yml添加配置
spring: redis: port: 6379 host: ***.***.***.*** password: 123456
RedisLockRegistry的配置
package com.lzx.demo.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.integration.redis.util.RedisLockRegistry; /** * 描述:锁配置 * * @Auther: lzx * @Date: 2019/6/17 15:06 */ @Configuration public class RedisLockConfiguration { @Bean public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){ return new RedisLockRegistry(redisConnectionFactory,"spring-cloud"); } }
二.使用分布式锁
1)自定义分布式锁的注解RedisLock
/** * 用于标记redis锁 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RedisLock { /** * 可使用SpEL传方法参数 * @return */ String value() default ""; /** * redis锁的key值 * @return */ String lockKey() default ""; }
2)使用aop实现锁的获取和释放(切面中的具体逻辑根据实际情况来写)
package com.apps.lock; import com.apps.bcodemsg.MsgResponse;import com.apps.redis.util.SerializeUtil; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.redis.util.RedisLockRegistry; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; /** * redis分布式锁的切面 */ @Aspect @Component public class RedisLockAspect { @Autowired private RedisLockRegistry redisLockRegistry; @Around(value = "@annotation(redisLock)") public synchronized Object redisLock(ProceedingJoinPoint joinPoint, RedisLock redisLock) { Logger mLog = LoggerFactory.getLogger(SerializeUtil.class); Object output = null; try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Object[] arguments = joinPoint.getArgs(); Field[] field = arguments[0].getClass().getDeclaredFields(); String value = ""; for (int j = 0; j < field.length; j++) { boolean fieldHasAnno = field[j].isAnnotationPresent(RedisLockKey.class); if (fieldHasAnno) { RedisLockKey fieldAnno = field[j].getAnnotation(RedisLockKey.class); //输出注解属性 String age = fieldAnno.value(); String name = field[j].getName(); name = name.substring(0, 1).toUpperCase() + name.substring(1); Method m = arguments[0].getClass().getMethod("get" + name); value = (String) m.invoke(arguments[0]); System.out.println(value); } } // 获取锁的key Object lockKey = value; if (lockKey == null || StringUtils.isBlank((String) lockKey)) { lockKey = "publistLock"; } Lock lock = redisLockRegistry.obtain(lockKey); try { boolean ifLock = lock.tryLock(3, TimeUnit.SECONDS); // mLog.info("线程[{}]是否获取到了锁:{ }", Thread.currentThread().getName(), ifLock); /* * 可以获取到锁,说明当前没有线程在执行该方法 */ if (ifLock) { output = joinPoint.proceed(); } else { MsgResponse msgResponse = new MsgResponse(); msgResponse.setCode(400); msgResponse.setMsg("服务异常!!!"); // mLog.info("线程[{}]未获取到锁,目前锁详情信息为:{}", Thread.currentThread().getName(), lock); return msgResponse; } } catch (Exception e) { // mLog.error("执行核心奖励扫描时出错:{}", e.getMessage()); } finally { // mLog.info("尝试解锁[{}]", lockKey); try { lock.unlock(); // mLog.info("[{}]解锁成功", lockKey); } catch (Exception e) { // mLog.error("解锁dealAction出错:{}", e.getMessage()); } } } catch (Throwable e) { mLog.error("aop redis distributed lock error:{}", e.getLocalizedMessage()); } return output; } }
3)使用RedisLock注解实现分布式锁
@LzxLockDistributed(value = "redisLockRegistry",time = 60) public String redisLockTest() throws InterruptedException { if(inventory >= 5){ return "已经抢购完了~~~"; } String s = strArr[inventory]; Thread.sleep(10*1000); inventory++; return s; }
本文部分转载自:
https://blog.csdn.net/github_35976996/article/details/93909359
来源:https://www.cnblogs.com/wsxdev/p/12015100.html