redisson分布式ロックの接面プログラミング

11777 ワード

  application.properties       :
spring.redislocal.host: redis://127.0.0.1
spring.redislocal.port: 6379
spring.redislocal.password: 111111
spring.redislocal.sleeptime: 10000

redisツールクラスの作成:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.util.SortedMap;
import java.util.TreeMap;

public class RedisUtils {

    private static Logger logger= LoggerFactory.getLogger(RedisUtils.class);

    private static RedisUtils redisUtils;

    private static RedissonClient redissonClient;

    private RedisUtils(){}

    /**
     *       
     * @return
     */
    public static RedisUtils getInstance(){
        if(redisUtils==null)
            synchronized (RedisUtils.class) {
                if(redisUtils==null) redisUtils=new RedisUtils();
            }
        return redisUtils;
    }


    /**
     *   config  Redisson
     * Redisson     Redis Server    
     * @param config
     * @return
     */
    public static RedissonClient getRedisson(Config config){
        RedissonClient redisson= Redisson.create(config);
        logger.info("    Redis Server");
        return redisson;
    }

    /**
     *   ip       Redisson
     * @param ip
     * @param port
     * @return
     */
    public static RedissonClient getRedisson(String ip,String port){
        Config config=new Config();
        config.useSingleServer().setAddress(ip+":"+port);
        RedissonClient redisson=Redisson.create(config);
        logger.info("    Redis Server"+"\t"+"  "+ip+":"+port+"   ");
        return redisson;
    }

    /**
     *   Redisson     
     * @param redisson
     */
    public static void closeRedisson(RedissonClient redisson){
        redisson.shutdown();
        logger.info("    Redis Client  ");
    }

    /**
     *        
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RBucket getRBucket(RedissonClient redisson, String objectName){
        RBucket bucket=redisson.getBucket(objectName);
        return bucket;
    }

    /**
     *   Map  
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RMap getRMap(RedissonClient redisson, String objectName){
        RMap map=redisson.getMap(objectName);
        return map;
    }

    /**
     *       
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RSortedSet getRSortedSet(RedissonClient redisson, String objectName){
        RSortedSet sortedSet=redisson.getSortedSet(objectName);
        return sortedSet;
    }

    /**
     *     
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RSet getRSet(RedissonClient redisson, String objectName){
        RSet rSet=redisson.getSet(objectName);
        return rSet;
    }

    /**
     *     
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RList getRList(RedissonClient redisson,String objectName){
        RList rList=redisson.getList(objectName);
        return rList;
    }

    /**
     *     
     * @param redisson
     * @param objectName
     * @return
     */
    public  RQueue getRQueue(RedissonClient redisson,String objectName){
        RQueue rQueue=redisson.getQueue(objectName);
        return rQueue;
    }

    /**
     *       
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RDeque getRDeque(RedissonClient redisson,String objectName){
        RDeque rDeque=redisson.getDeque(objectName);
        return rDeque;
    }

    /**
     *        Redisson 1.2  
     *  1.2.2     
     * @param redisson
     * @param objectName
     * @return
     */
     public static  RBlockingQueue getRBlockingQueue(RedissonClient redisson,String objectName){
     RBlockingQueue rb=redisson.getBlockingQueue(objectName);
     return rb;
     }

    /**
     *    
     * @param redisson
     * @param objectName
     * @return
     */
    public static RLock getRLock(RedissonClient redisson,String objectName){
        RLock rLock=redisson.getLock(objectName);
        return rLock;
    }

    /**
     *      
     * @param redisson
     * @param objectName
     * @return
     */
    public static RAtomicLong getRAtomicLong(RedissonClient redisson,String objectName){
        RAtomicLong rAtomicLong=redisson.getAtomicLong(objectName);
        return rAtomicLong;
    }

    /**
     *      
     * @param redisson
     * @param objectName
     * @return
     */
    public static RCountDownLatch getRCountDownLatch(RedissonClient redisson,String objectName){
        RCountDownLatch rCountDownLatch=redisson.getCountDownLatch(objectName);
        return rCountDownLatch;
    }

    /**
     *      Topic
     * @param redisson
     * @param objectName
     * @return
     */
    public static  RTopic getRTopic(RedissonClient redisson,String objectName){
        RTopic rTopic=redisson.getTopic(objectName);
        return rTopic;
    }

    /**
     *           key
     * redis key       "DistRedisLock+" + lockKey + @DistRedisLockKey
* * @param point * @param lockKey * @return */ public static String getLockKey(ProceedingJoinPoint point, String lockKey) { try { lockKey = "DistRedisLock:" + lockKey; Object[] args = point.getArgs(); if (args != null && args.length > 0) { MethodSignature methodSignature = (MethodSignature)point.getSignature(); Annotation[][] parameterAnnotations = methodSignature.getMethod().getParameterAnnotations(); SortedMap keys = new TreeMap<>(); for (int i = 0; i < parameterAnnotations.length; i ++) { RedisLockKey redisLockKey = getAnnotation(RedisLockKey.class, parameterAnnotations[i]); if (redisLockKey != null) { Object arg = args[i]; if (arg != null) { keys.put(redisLockKey.order(), arg.toString()); } } } if (keys != null && keys.size() > 0){ for (String key : keys.values()) { lockKey += key; } } } return lockKey; } catch (Exception e) { logger.error("getLockKey error.", e); } return null; } /** * * @param annotationClass * @param annotations * @param * @return */ private static T getAnnotation(final Class annotationClass, final Annotation[] annotations) { if (annotations != null && annotations.length > 0) { for (final Annotation annotation : annotations) { if (annotationClass.equals(annotation.annotationType())) { return (T) annotation; } } } return null; } public static RedissonClient createClient(String address , String pass) { if(redissonClient == null) { synchronized (RedisUtils.class) { if(redissonClient == null) { Config config = new Config(); SingleServerConfig singleSerververConfig = config.useSingleServer(); singleSerververConfig.setAddress(address); singleSerververConfig.setPassword(pass); redissonClient = RedisUtils.getInstance().getRedisson(config); } } } return redissonClient; } }

 
書き込み注記RedisLock:
import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RedisLock {
    /**
     *   key
     *          ,        @P4jSynKey  ,          
* redis key "DistRedisLock+" + lockKey + @RedisLockKey
*/ String lockKey(); /** * * , 5
*/ long keepMills() default 5 * 1000; /** * , * @return */ long maxSleepMills() default 20 * 1000; }

書き込み注記RedisLockKey:
import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RedisLockKey {
    /**
     * key       
     */
    int order() default 0;
}

書き込みスライス:
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.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
public class RedisLockAspect {

    private static Logger logger= LoggerFactory.getLogger(RedisLockAspect.class);

    @Value("${spring.redislocal.host}:${spring.redislocal.port}")
    String address;

    @Value("${spring.redislocal.password}")
    String password;

    @Value("${spring.redislocal.sleeptime}")
    int sleepTime ;

    @Around("execution(* com.juphoon.coachtalk.appserver.service..*(..))&& @annotation(RedisLock)")
    public Object lock(ProceedingJoinPoint point) throws Throwable {
        RLock lock = null;
        Boolean status = false;
        Object object = null;
        logger.info("into Aspect!");
        try {
            RedisLock redisLock = getDistRedisLockInfo(point);
            RedisUtils redisUtils = RedisUtils.getInstance();
            RedissonClient redissonClient = RedisUtils.createClient(address, password);

            String lockKey = redisUtils.getLockKey(point, redisLock.lockKey());

            lock = redisUtils.getRLock(redissonClient, lockKey);
            if (lock != null) {
                status = lock.tryLock(redisLock.maxSleepMills(), redisLock.keepMills(), TimeUnit.MILLISECONDS);
                if (status) {
                    object = point.proceed();
                }

            }
        } finally {
            if (lock != null && status) {
                lock.unlock();
            }
        }
        return object;
    }

    private RedisLock getDistRedisLockInfo(ProceedingJoinPoint point) {
        try {
            MethodSignature methodSignature = (MethodSignature) point.getSignature();
            Method method = methodSignature.getMethod();
            return method.getAnnotation(RedisLock.class);
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
        return null;
    }
}

 
実装の呼び出し:
@RedisLock(lockKey = "lockKey", keepMills = 15000)
public void updateXXX(@RedisLockKey(order = 1) Long userId, @RedisLockKey(order = 0) Long advisorId) {

}