摘要:當(dāng)觸發(fā)定時(shí)任務(wù)時(shí),一臺(tái)服務(wù)的任務(wù)進(jìn)入切面,通過方法為唯一的加鎖,如果當(dāng)前不存在,將放入緩存,并返回通過設(shè)置鎖超時(shí)時(shí)間,結(jié)束后跳出執(zhí)行定時(shí)任務(wù)方法。
問題描述
將帶有定時(shí)任務(wù)的項(xiàng)目部署在單臺(tái)測試環(huán)境上,完全沒問題。生產(chǎn)上是兩臺(tái)集群服務(wù)器,項(xiàng)目部署上去發(fā)現(xiàn)定時(shí)任務(wù)的模塊同時(shí)在兩臺(tái)機(jī)器上各執(zhí)行了一遍,這將會(huì)導(dǎo)致其他意外的發(fā)生。
解決方案----redis分布式鎖使用redis分布式鎖,為定時(shí)任務(wù)唯一指定的key加鎖,并設(shè)置鎖超時(shí)時(shí)間。當(dāng)觸發(fā)定時(shí)任務(wù)時(shí),一臺(tái)服務(wù)的任務(wù)進(jìn)入切面,通過setNX(key,value)方法為唯一的key加鎖,如果當(dāng)前key不存在,將放入緩存,并返回true,通過expire(key,second)設(shè)置鎖超時(shí)時(shí)間,結(jié)束后跳出執(zhí)行定時(shí)任務(wù)方法。第二臺(tái)服務(wù)任務(wù)進(jìn)入時(shí),設(shè)置鎖的時(shí)候發(fā)現(xiàn)該鎖已存在于緩存,并返回false,不跳轉(zhuǎn)到執(zhí)行定時(shí)任務(wù)方法。
核心代碼1.分布式鎖切面
@Aspect @Slf4j @Component public class CacheLockAspect { private static final String LOCK_VALUE = "locked"; @Autowired private RedisConnection connection; @Around("execution(* *.*(..)) && @annotation(com.common.annotation.CacheLock)") public void cacheLockPoint(ProceedingJoinPoint pjp) { Method cacheMethod = null; for (Method method : pjp.getTarget().getClass().getMethods()) { if (null!=method.getAnnotation(CacheLock.class)){ cacheMethod = method; break; } } try { String lockKey = cacheMethod.getAnnotation(CacheLock.class).lockedPrefix(); long timeOut = cacheMethod.getAnnotation(CacheLock.class).expireTime(); if(null == lockKey){ throw new ManagerException(ErrorMsgEnum.LOCK_NAME_EMPTY); } if (connection.setNX(lockKey.getBytes(),LOCK_VALUE.getBytes())) { connection.expire(lockKey.getBytes(),timeOut); log.info("method:{}獲取鎖:{},開始運(yùn)行!",cacheMethod,lockKey); pjp.proceed(); return; } log.info("method:{}未獲取鎖:{},運(yùn)行失?。?,cacheMethod,lockKey); } catch (Throwable e) { log.error("method:{},運(yùn)行錯(cuò)誤!",cacheMethod,e); throw new ManagerException(ErrorMsgEnum.LOCK_JOB_ERROR,e); } } }
2.手寫方法級(jí)注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CacheLock { String lockedPrefix() default ""; //redis 鎖key的前綴 long expireTime() default 10; //key在redis里存在的時(shí)間,1000S }
3.定時(shí)任務(wù)服務(wù)
@Slf4j @Service public class TimeTaskService { /** * 執(zhí)行定時(shí)任務(wù) **/ @Scheduled(cron = "0 0 1 * * ?") @CacheLock(lockedPrefix = "TimeTaskService",expireTime=30) public void executeTask() { System.out.println("hello world!"); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72599.html
摘要:考拉訂單流推送申報(bào)單推送物流信息等供應(yīng)鏈相關(guān)業(yè)務(wù)已接入分片任務(wù),極大提高了業(yè)務(wù)吞吐量降低壓力,提升了通關(guān)效率。支撐雙十一黑五雙十二等大促,高峰期統(tǒng)一暫停非關(guān)鍵定時(shí)任務(wù),讓出系統(tǒng)資源,提高業(yè)務(wù)系統(tǒng)穩(wěn)定性。 此文已由作者楊凱明授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)。 1.背景 目前項(xiàng)目中使用的定時(shí)任務(wù)框架存在下面這些問題 沒有統(tǒng)一的定時(shí)任務(wù)管理平臺(tái) 目前項(xiàng)目...
摘要:分布式鎖實(shí)現(xiàn)方式前言目前幾乎很多大型網(wǎng)站及應(yīng)用都是分布式部署的,分布式場景中的數(shù)據(jù)一致性問題一直是一個(gè)比較重要的話題?;跀?shù)據(jù)庫實(shí)現(xiàn)分布式鎖基于緩存等實(shí)現(xiàn)分布式鎖基于實(shí)現(xiàn)分布式鎖。 前言 分布式鎖,是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式 在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問這些資源的時(shí)候,往往需要互斥...
摘要:分布式鎖實(shí)現(xiàn)方式前言目前幾乎很多大型網(wǎng)站及應(yīng)用都是分布式部署的,分布式場景中的數(shù)據(jù)一致性問題一直是一個(gè)比較重要的話題。基于數(shù)據(jù)庫實(shí)現(xiàn)分布式鎖基于緩存等實(shí)現(xiàn)分布式鎖基于實(shí)現(xiàn)分布式鎖。 前言 分布式鎖,是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式 在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問這些資源的時(shí)候,往往需要互斥...
摘要:綜合上述缺點(diǎn),小明痛定思痛,提出了經(jīng)營方式二。當(dāng)客戶下單,小明按送達(dá)地點(diǎn)標(biāo)注好,依次放在一個(gè)地方。因此,有強(qiáng)一致性要求的數(shù)據(jù),不能放緩存。迅速判斷出,請求所攜帶的是否合法有效。 showImg(https://segmentfault.com/img/bVbvHHL?w=1341&h=448); 絕大部分寫業(yè)務(wù)的程序員,在實(shí)際開發(fā)中使用 Redis 的時(shí)候,只會(huì) Set Value 和...
閱讀 3207·2021-09-29 09:34
閱讀 3561·2021-09-10 10:51
閱讀 1961·2021-09-10 10:50
閱讀 6768·2021-08-12 13:31
閱讀 3009·2019-08-30 15:54
閱讀 1585·2019-08-30 15:44
閱讀 1435·2019-08-29 12:26
閱讀 2664·2019-08-26 18:36