zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    MFC
    驱动学习
    Ubuntu下为Apache简单配置SSL的方法(HTTPS的实现)
    在linux下helloworld的C程序
    swift安装,linux
    gcc,cc,g++,CC的区别
    ldconfig与 /etc/ld.so.conf
    ubuntu16.04,mysql5.7重启不成功。Restarting mysql (via systemctl): mysql.serviceJob for mysql.service failed because the control process exited with error code. See "systemctl status mysql.service"
    linux .o,.a,.so文件
    zipgateway-2-61-0的安装
  • 原文地址:https://www.cnblogs.com/wsxdev/p/12015100.html
Copyright © 2011-2022 走看看