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
