本篇內(nèi)容主要講解“如何用AOP注解方式實(shí)現(xiàn)redis分布式搶占鎖”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何用AOP注解方式實(shí)現(xiàn)redis分布式搶占鎖”吧!
太平網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
很多項(xiàng)目中都會(huì)有一些需要做定時(shí)跑批的任務(wù)需求,大多數(shù)是通過(guò)spring注解的方式實(shí)現(xiàn)的,但是到了生產(chǎn)環(huán)境,多節(jié)點(diǎn)的部署可能會(huì)造成定時(shí)任務(wù)的多節(jié)點(diǎn)同時(shí)觸發(fā)而可能會(huì)出現(xiàn)臟數(shù)據(jù)。之前的處理方案是通過(guò)在字典里配置指定生產(chǎn)節(jié)點(diǎn)處理定時(shí)任務(wù)。雖然此方法也能實(shí)現(xiàn)需求,但總覺(jué)得很low,所以自己就通過(guò)JAVA的AOP方式利用redis實(shí)現(xiàn)了一套分布式搶占鎖,通過(guò)注解的方式解決生產(chǎn)環(huán)境多節(jié)點(diǎn)部署帶來(lái)的定時(shí)任務(wù)觸發(fā)。
廢話不多說(shuō),直接上代碼--> 1、先自定義一個(gè)注解
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) // 在運(yùn)行時(shí)可以獲取 public @interface RedisLock { }
2、再新建一個(gè)切面類
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】開始進(jìn)入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 代理執(zhí)行失敗"); } } } }
3、在需求做定時(shí)任務(wù)的方法上添加自定義注解@RedisLock
/** * 測(cè)試批處理 */ @Override @RedisLock public void syncTest() { try{ //獲取所有需要同步狀態(tài)的付款單據(jù) ListallNeedSyncStatusForPayment = 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())+"結(jié)束***********************************************"); }catch (Exception e){ logger.error(e.getMessage()); } }
4、注意事項(xiàng): 4.1 注解不要放在service層 反射代理會(huì)繞過(guò)spring注解
補(bǔ)充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(); } /** * 搶占執(zhí)行權(quán) 鎖 * @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); } } } }
到此,相信大家對(duì)“如何用AOP注解方式實(shí)現(xiàn)redis分布式搶占鎖”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!