springboot实现分布式锁(spring integration,redis)

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

posted @ 2019-12-10 10:25  NewBBBB  阅读(3700)  评论(0编辑  收藏  举报