您好,登錄后才能下訂單哦!
本篇內容主要講解“如何用AOP注解方式實現redis分布式搶占鎖”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何用AOP注解方式實現redis分布式搶占鎖”吧!
很多項目中都會有一些需要做定時跑批的任務需求,大多數是通過spring注解的方式實現的,但是到了生產環境,多節點的部署可能會造成定時任務的多節點同時觸發而可能會出現臟數據。之前的處理方案是通過在字典里配置指定生產節點處理定時任務。雖然此方法也能實現需求,但總覺得很low,所以自己就通過JAVA的AOP方式利用redis實現了一套分布式搶占鎖,通過注解的方式解決生產環境多節點部署帶來的定時任務觸發。
廢話不多說,直接上代碼--> 1、先自定義一個注解
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、再新建一個切面類
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、在需求做定時任務的方法上添加自定義注解@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、注意事項: 4.1 注解不要放在service層 反射代理會繞過spring注解
補充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); } } } }
到此,相信大家對“如何用AOP注解方式實現redis分布式搶占鎖”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。