基于SpringBoot AOP面向切面編程實(shí)現(xiàn)Redis分布式鎖

基于SpringBoot AOP面向切面編程實(shí)現(xiàn)Redis分布式鎖
基于SpringBoot AOP面向切面編程實(shí)現(xiàn)Redis分布式鎖
基于SpringBoot AOP面向切面編程實(shí)現(xiàn)Redis分布式鎖

鎖定的目標(biāo)是確保相互排斥其訪問(wèn)的資源。實(shí)際上堤尾,此資源通常是字符串肝劲。使用redis實(shí)現(xiàn)鎖主要是將資源放入redis中并利用其原子性。當(dāng)其他線程訪問(wèn)時(shí)郭宝,如果Redis中已經(jīng)存在此資源辞槐,則不允許進(jìn)行某些后續(xù)操作。

Spring Boot通過(guò)RedisTemplate使用Redis粘室,在實(shí)際使用過(guò)程中榄檬,分布式鎖可以在封裝后在方法級(jí)別使用,這樣使用起來(lái)就更方便了育特,無(wú)需到處獲取和釋放鎖丙号。

首先先朦,定義一個(gè)注解:

@Target({ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Inherited  
public @interface RedisLock {

     //鎖定的資源缰冤,redis的鍵
    String value() default "default";

    //鎖定保持時(shí)間(以毫秒為單位) 
    long keepMills() default 30000;

    //失敗時(shí)執(zhí)行的操作
    LockFailAction action() default LockFailAction.CONTINUE;

    //失敗時(shí)執(zhí)行的操作--枚舉
    public enum LockFailAction{  
        GIVEUP,  
        CONTINUE;  
    }
    //重試的間隔
    long sleepMills() default 200;
    //重試次數(shù)
    int retryTimes() default 5;  
}

具有分布式鎖的Bean

@Configuration 
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class DistributedLockAutoConfiguration {    
    @Bean    
    @ConditionalOnBean(RedisTemplate.class)    
    public DistributedLock redisDistributedLock(RedisTemplate redisTemplate){       
        return new RedisDistributedLock(redisTemplate);   
    }
}

面向切面編程-定義切面

@Aspect  
@Configuration  
@ConditionalOnClass(DistributedLock.class)  
@AutoConfigureAfter(DistributedLockAutoConfiguration.class)  
public class DistributedLockAspectConfiguration {

    private final Logger logger = LoggerFactory.getLogger(DistributedLockAspectConfiguration.class);

    @Autowired  
    private DistributedLock distributedLock;

    @Pointcut("@annotation(com.itopener.lock.redis.spring.boot.autoconfigure.annotations.RedisLock)")  
    private void lockPoint(){

    }

    @Around("lockPoint()")  
    public Object around(ProceedingJoinPoint pjp) throws Throwable{  
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();  
        RedisLock redisLock = method.getAnnotation(RedisLock.class);  
        String key = redisLock.value();  
        if(StringUtils.isEmpty(key)){  
            Object\[\] args = pjp.getArgs();  
            key = Arrays.toString(args);  
        }  
        int retryTimes = redisLock.action().equals(LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0;  
         //獲取分布式鎖 
        boolean lock = distributedLock.lock(key, redisLock.keepMills(), retryTimes, redisLock.sleepMills());  
        if(!lock) {  
            logger.debug("get lock failed : " + key);  
            return null;  
        }

       //執(zhí)行方法之后,釋放分布式鎖
        logger.debug("get lock success : " + key);  
        try {  
            return pjp.proceed();   //執(zhí)行方法
        } catch (Exception e) {  
            logger.error("execute locked method occured an exception", e);  
        } finally {  
            boolean releaseResult = distributedLock.releaseLock(key);  //釋放分布式鎖
            logger.debug("release lock :" + key + (releaseResult ?" success" : "failed"));  
        }  
        return null;  
    }  
}

使用方法

  • 進(jìn)入該方法時(shí)喳魏,占用分布式鎖棉浸,
  • 方法執(zhí)行完成時(shí),釋放分布式鎖
  • 使用同一個(gè)資源刺彩,如your-custom-service-redis-key的多個(gè)函數(shù)迷郑,搶占同一個(gè)鎖。誰(shuí)搶到誰(shuí)先執(zhí)行创倔。
@RedisLock(value="your-custom-service-redis-key")
public void  serviceMethod(){
  //正常寫方法實(shí)現(xiàn)
}

歡迎關(guān)注我的博客嗡害,里面有很多精品合集

  • 本文轉(zhuǎn)載注明出處(必須帶連接,不能只轉(zhuǎn)文字):字母哥博客畦攘。

覺(jué)得對(duì)您有幫助的話霸妹,幫我點(diǎn)贊、分享知押!您的支持是我不竭的創(chuàng)作動(dòng)力叹螟! 鹃骂。另外,筆者最近一段時(shí)間輸出了如下的精品內(nèi)容罢绽,期待您的關(guān)注畏线。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市良价,隨后出現(xiàn)的幾起案子寝殴,更是在濱河造成了極大的恐慌,老刑警劉巖明垢,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杯矩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡袖外,警方通過(guò)查閱死者的電腦和手機(jī)史隆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)曼验,“玉大人泌射,你說(shuō)我怎么就攤上這事△拚眨” “怎么了熔酷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)豺裆。 經(jīng)常有香客問(wèn)我拒秘,道長(zhǎng),這世上最難降的妖魔是什么臭猜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任躺酒,我火速辦了婚禮,結(jié)果婚禮上蔑歌,老公的妹妹穿的比我還像新娘羹应。我一直安慰自己,他們只是感情好次屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布园匹。 她就那樣靜靜地躺著,像睡著了一般劫灶。 火紅的嫁衣襯著肌膚如雪裸违。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天本昏,我揣著相機(jī)與錄音供汛,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛紊馏,可吹牛的內(nèi)容都是我干的料饥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼朱监,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岸啡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起赫编,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤巡蘸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后擂送,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體悦荒,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年嘹吨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搬味。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蟀拷,死狀恐怖碰纬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情问芬,我是刑警寧澤悦析,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站此衅,受9級(jí)特大地震影響强戴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挡鞍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一骑歹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匕累,春花似錦陵刹、人聲如沸默伍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)也糊。三九已至炼蹦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狸剃,已是汗流浹背掐隐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虑省。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓匿刮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親探颈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熟丸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359