AOP annotations manner redis distributed to seize the lock

Copyright notice: reproduced please specify, thank you https://blog.csdn.net/qrainly/article/details/86544382

Summary

Many projects will have some need to do timed run batch mission requirements, mostly achieved through the spring as annotations, but to the production environment, multi-node deployments could result in a multi-node timed tasks simultaneously trigger may appear dirty data. The solution is treated before processing timing configuration tasks specified node in the dictionary production. Although this method can achieve demand, but I felt quite low, so their regular tasks on multi-node deployment brings triggered by the use of AOP way redis JAVA implements a distributed lock seize, to solve production environment by way of comment.

Ado, directly on the code ->
1, first customize a comment

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author v_liuwen
 * @date 2018/12/27
 */
@Target({ElementType.METHOD,ElementType.TYPE}) // 作用到类,方法,接口上等
@Retention(RetentionPolicy.RUNTIME) // 在运行时可以获取
public @interface RedisLock {
}

2, then a new class section


import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import top.qrainly.bj_demo.job.springtask.scheduleJob.utils.RedisLockUtils;

/**
 * @author v_liuwen
 * @date 2018/12/27
 */
@Aspect
@Component
public class RedisLockAspect {

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

    /**
     * 切面 加有 RedisLock 的 service 方法
     */
    @Pointcut("@annotation(redisLock)")
    private void cutMethod(RedisLock redisLock) {
    }

    @Before("cutMethod(redisLock)")
    public void doAccessCheck(JoinPoint point,RedisLock redisLock) throws NoSuchMethodException {
        logger.info("********************************【Before】开始进入AOP切入**************************************");
    }

    @After("cutMethod(redisLock)")
    public void after(JoinPoint point,RedisLock redisLock) {
        logger.info("********************************【after】AOP切入完成**************************************");
    }

    @AfterThrowing("cutMethod(redisLock)")
    public void doAfterThrow(RedisLock redisLock) {
        logger.info("AfterThrowing...");
    }


    @Around("cutMethod(redisLock)")
    public void around(ProceedingJoinPoint point,RedisLock redisLock){
        String name = point.getSignature().getName();
        Class<?> classTarget = point.getTarget().getClass();
        System.out.println("--------------------------------------->>>AOP切入 方法名:"+name+"<<<-----------------------------------------------------");
        System.out.println("--------------------------------------->>>AOP切入 类名:"+classTarget.getSimpleName()+"<<<-----------------------------------------------------");
        //获取redis锁
        Boolean lock = RedisLockUtils.acquireRedisLock(StringUtils.join(classTarget.getSimpleName(),name), 5);
        if(lock){
            try {
                point.proceed();
            } catch (Throwable throwable) {
               logger.error("AOP 代理执行失败");
            }
        }
    }


}

3, added to the method needs to do regular tasks of the custom annotation @RedisLock


    /**
     * 测试批处理
     */
    @Override
    @RedisLock
    public void syncTest() {
        try{
            //获取所有需要同步状态的付款单据
            List<String> allNeedSyncStatusForPayment = batchDAO.getAllNeedSyncStatusForPayment();
            SimpleDateFormat sdf = new SimpleDateFormat();
            System.out.println("*****************************************"+sdf.format(new Date())+"开始***********************************************");
            System.out.println(JSON.toJSONString(allNeedSyncStatusForPayment));
            System.out.println("*****************************************"+sdf.format(new Date())+"结束***********************************************");
        }catch (Exception e){
            logger.error(e.getMessage());
        }
    }

4 Note:
4.1 annotation layer reflection not on the service proxy bypass spring notes

Supplementary RedisLockUtils

/**
 * @author v_liuwen
 * @date 2018/12/26
 */
public class RedisLockUtils {

    /**
     * 日志打印
     */
    private static Logger logger = LoggerFactory.getLogger(RedisLockUtils.class);

    private static Jedis jedis;

    /**
     * 获取jedis
     *
     * @return
     */
    public static Jedis getJedis() {
        Jedis jedis = SpringContextHolder.getBean(JedisUtils.class).getResource();
        return jedis;

    }
    /**
     * 释放jedis
     *
     * @return
     */
    public static void releaseJedis(Jedis jedis) {
        jedis.close();
    }

    /**
     * 抢占执行权 锁
     * @param lockName
     * @param lockExpire
     * @return
     */
    public static Boolean acquireRedisLock(String lockName,int lockExpire){
        Jedis jedis = getJedis();
        String identifier = UUID.randomUUID().toString();
        String lockKey = lockName;
        try{
            if (jedis.setnx(lockKey, identifier) == 1) {
                logger.info("Get lock {} success:{}.",lockName,identifier);
                jedis.expire(lockKey,lockExpire);
                if (jedis.ttl(lockKey) == -1) {
                    jedis.expire(lockKey, lockExpire);
                }
                return true;
            }
            return false;
        }catch (Exception e){
            logger.error(e.getMessage());
            return false;
        }finally {
            if(jedis !=null){
                releaseJedis(jedis);
            }
        }
    }
}

Paper Zhongjue know this practice is essential

Guess you like

Origin blog.csdn.net/qrainly/article/details/86544382