国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪

這篇具有很好參考價(jià)值的文章主要介紹了springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

redis作為用的非常多的緩存數(shù)據(jù)庫(kù),在多線程場(chǎng)景下,可能會(huì)出現(xiàn)數(shù)據(jù)庫(kù)與redis數(shù)據(jù)不一致的現(xiàn)象

數(shù)據(jù)不一致的現(xiàn)象:https://blog.csdn.net/m0_73700925/article/details/133447466

這里采用aop+redis來(lái)解決這個(gè)方法:

  1. 刪除緩存
  2. 更新數(shù)據(jù)庫(kù)
  3. 延時(shí)一定時(shí)間,比如500ms
  4. 刪除緩存

這里之所以要延時(shí)一段時(shí)間再刪除,是為了避免多線程情況下,更新數(shù)據(jù)庫(kù)的操作還沒執(zhí)行,就執(zhí)行了第二次刪除緩存的操作,此時(shí)如果有請(qǐng)求進(jìn)來(lái),就會(huì)讀取數(shù)據(jù)庫(kù)并將數(shù)據(jù)寫入緩存,這時(shí)再更新數(shù)據(jù)庫(kù)就會(huì)導(dǎo)致數(shù)據(jù)不一致的問題

兩次刪除緩存是因?yàn)榈谝淮蝿h除緩存后,這時(shí)如果有請(qǐng)求進(jìn)來(lái),得到了數(shù)據(jù)并寫入redis,然后再更新數(shù)據(jù)庫(kù),就會(huì)導(dǎo)致數(shù)據(jù)不一致

  1. 自定義注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.METHOD)
public @interface ClearAndReloadCache {
    String name() default "";
}
  1. 編寫切面,以自定義注解作為切入點(diǎn)
@Aspect
@Component
public class ClearAndReloadCacheAspect {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Around("@annotation(clearAndReloadCache)")
    public Object innerAround(ProceedingJoinPoint proceedingJoinPoint, ClearAndReloadCache clearAndReloadCache) throws Throwable {
        System.out.println("----------- 環(huán)繞通知 -----------");
        System.out.println("環(huán)繞通知的目標(biāo)方法名:" + proceedingJoinPoint.getSignature().getName());
        Signature signature1 = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature1;
        Method targetMethod = methodSignature.getMethod();//方法對(duì)象
        ClearAndReloadCache annotation = targetMethod.getAnnotation(ClearAndReloadCache.class);//反射得到自定義注解的方法對(duì)象
        String name = annotation.name();
        // 延時(shí)雙刪中的第一次刪除緩存
        Set<String> keys = stringRedisTemplate.keys("*" + name + "*");
        stringRedisTemplate.delete(keys);

        Object proceed = null;
        // 執(zhí)行業(yè)務(wù)層代碼
        proceed = proceedingJoinPoint.proceed();

        // 執(zhí)行延遲雙刪中的第二次刪除緩存
        // 開啟新線程是為了避免主線程堵塞等待
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                Set<String> keys2 = stringRedisTemplate.keys("*" + name + "*");
                stringRedisTemplate.delete(keys2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        return proceed;
    }
}

切面也可以寫成這樣,更方便理解

@Aspect
@Component
public class ClearAndReloadCacheAspect {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Pointcut("@annotation(com.toptolink.iot.permission.annotation.ClearAndReloadCache)")
    public void pointCut(){

    }

    @Around("pointCut()")
    public Object innerAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("----------- 環(huán)繞通知 -----------");
        System.out.println("環(huán)繞通知的目標(biāo)方法名:" + proceedingJoinPoint.getSignature().getName());
        Signature signature1 = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature1;
        Method targetMethod = methodSignature.getMethod();//方法對(duì)象
        ClearAndReloadCache annotation = targetMethod.getAnnotation(ClearAndReloadCache.class);//反射得到自定義注解的方法對(duì)象
        String name = annotation.name();
        // 延時(shí)雙刪中的第一次刪除緩存
        Set<String> keys = stringRedisTemplate.keys("*" + name + "*");
        stringRedisTemplate.delete(keys);

        Object proceed = null;
        // 執(zhí)行業(yè)務(wù)層代碼
        proceed = proceedingJoinPoint.proceed();

        // 執(zhí)行延遲雙刪中的第二次刪除緩存
        // 開啟新線程是為了避免主線程堵塞等待
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                Set<String> keys2 = stringRedisTemplate.keys("*" + name + "*");
                stringRedisTemplate.delete(keys2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        return proceed;
    }
}
  1. 業(yè)務(wù)層代碼
    controller
@ApiOperation("小程序小程序平臺(tái)通用-工單詳情")
    @GetMapping("/queryWorkOrderDetail")
    @PreAuthorize(Permissions.YQZ_MAINTAIN)
    public DataResponseBody queryWorkOrderDetail(@RequestParam Long id) {
        return new DataResponseBody(iMaintainService.queryWorkOrderDetail(id));
    }

    /**
     * @return
     */
    @GetMapping("/TODOupdateById")
    @PreAuthorize(Permissions.YQZ_MAINTAIN)
    @ClearAndReloadCache(name = "getById")
    public DataResponseBody TODOupdateById(Long id, String customerFullName) {
        return new DataResponseBody(iMaintainService.TODOupdateById(id, customerFullName));
    }

我在queryWorkOrderDetail()中將查到的數(shù)據(jù)存入了redis中,redisService.set("getById"+id, json);文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-795907.html

  1. 測(cè)試
    首先需要通過idea多開啟一個(gè)程序,用于模擬多線程
    springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪,spring boot,redis,java
    springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪,spring boot,redis,java
    然后通過打斷點(diǎn)的方式
    springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪,spring boot,redis,java
  • 首先調(diào)用查詢接口,此時(shí)會(huì)將數(shù)據(jù)存入redis中
  • 然后調(diào)用修改接口,進(jìn)入debug模式,當(dāng)?shù)谝淮蝿h除緩存后,不要往下走
  • 再次調(diào)用查詢接口,用于模擬多線程情況下的數(shù)據(jù)不一致情況
  • 這時(shí)redis又會(huì)存入數(shù)據(jù)
  • 接著就是更新數(shù)據(jù)庫(kù)的操作
  • 此時(shí)如果沒有第二次刪除緩存,就會(huì)出現(xiàn)數(shù)據(jù)不一致了
  • 所以第二次刪除緩存是很有必要的

到了這里,關(guān)于springboot自定義注解+aop+redis實(shí)現(xiàn)延時(shí)雙刪的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Spring】使用自定義注解方式實(shí)現(xiàn)AOP鑒權(quán)

    AOP,是一種面向切面編程,可以通過預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。 在軟件開發(fā)中,鑒權(quán)(Authentication)是一項(xiàng)非常重要的安全措施,用于驗(yàn)證用戶身份和權(quán)限。在應(yīng)用程序中,我們通常會(huì)使用AOP(Aspect-Oriented Programming)來(lái)實(shí)現(xiàn)鑒權(quán)功能

    2024年02月11日
    瀏覽(20)
  • Spring Boot學(xué)習(xí)隨筆- 實(shí)現(xiàn)AOP(JoinPoint、ProceedingJoinPoint、自定義注解類實(shí)現(xiàn)切面)

    Spring Boot學(xué)習(xí)隨筆- 實(shí)現(xiàn)AOP(JoinPoint、ProceedingJoinPoint、自定義注解類實(shí)現(xiàn)切面)

    學(xué)習(xí)視頻:【編程不良人】2021年SpringBoot最新最全教程 問題 現(xiàn)有業(yè)務(wù)層開發(fā)存在問題 額外功能代碼存在大量冗余 每個(gè)方法都需要書寫一遍額外功能代碼不利于項(xiàng)目維護(hù) Spring中的AOP AOP:Aspect 切面 + Oriented 面向 Programmaing 面向切面編程 Aspect(切面) = Advice(通知) + Pointcut(

    2024年02月04日
    瀏覽(43)
  • 【Spring AOP + 自定義注解 + 動(dòng)態(tài)數(shù)據(jù)源 實(shí)現(xiàn)主從庫(kù)切換&讀寫分離】—— 案例實(shí)戰(zhàn)

    【Spring AOP + 自定義注解 + 動(dòng)態(tài)數(shù)據(jù)源 實(shí)現(xiàn)主從庫(kù)切換&讀寫分離】—— 案例實(shí)戰(zhàn)

    ???????????????????????????????????????????? ?? S p r i n g A O P + 主從數(shù)據(jù)源切換 + 讀寫分離 + 自定義注解案例實(shí)戰(zhàn)! color{#FF1493}{Spring AOP + 主從數(shù)據(jù)源切換 + 讀寫分離 + 自定義注解 案例實(shí)戰(zhàn)!} Sp r in g A OP + 主從數(shù)據(jù)源切換 + 讀寫分離 + 自定義注解案例

    2024年02月15日
    瀏覽(21)
  • 圖文講解Redis延時(shí)雙刪原因及必要性

    圖文講解Redis延時(shí)雙刪原因及必要性

    目錄 一、前言 二、常見更新策略 2.1 先刪緩存,再更新數(shù)據(jù)庫(kù) 2.2 先更新數(shù)據(jù)庫(kù),再刪除緩存 2.3 普通雙刪 2.4 延遲雙刪 三、是否必要建議 我們?cè)趯?shí)際項(xiàng)目中經(jīng)常會(huì)使用到Redis緩存用來(lái)緩解數(shù)據(jù)庫(kù)壓力,但是當(dāng)更新數(shù)據(jù)庫(kù)時(shí),如何保證緩存及數(shù)據(jù)庫(kù)一致性,一般我們采用延時(shí)

    2024年02月16日
    瀏覽(20)
  • Springboot 中使用 Redisson+AOP+自定義注解 實(shí)現(xiàn)訪問限流與黑名單攔截

    Springboot 中使用 Redisson+AOP+自定義注解 實(shí)現(xiàn)訪問限流與黑名單攔截

    ??? 個(gè)人主頁(yè) :牽著貓散步的鼠鼠? ??? 系列專欄 :Java全棧-專欄 ??? 個(gè)人學(xué)習(xí)筆記,若有缺誤,歡迎評(píng)論區(qū)指正 ? 前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站AI學(xué)習(xí)網(wǎng)站。 目錄 前言 1.導(dǎo)入Redisson 引入依

    2024年02月21日
    瀏覽(21)
  • Spring Boot入門(23):基于AOP實(shí)現(xiàn)自定義注解攔截接口日志并保存入庫(kù) | 超級(jí)詳細(xì),建議收藏

    Spring Boot入門(23):基于AOP實(shí)現(xiàn)自定義注解攔截接口日志并保存入庫(kù) | 超級(jí)詳細(xì),建議收藏

    ? ? ? ? 在上兩期中,我們著重介紹了如何集成使用 Logback?與?log4j2?日志框架的使用,今天我們講解的主題依舊跟日志有關(guān),不過不是使用何種開源框架,而是自己動(dòng)手造。 ? ? ? ? Spring的核心之一AOP;AOP翻譯過來(lái)叫面向切面編程, 核心就是這個(gè)切面. 切面表示從業(yè)務(wù)邏輯中

    2024年02月11日
    瀏覽(28)
  • spring自定義注解+aop+@BindingParam

    2.1 聲明切面注解 ?2.1.1切面對(duì)應(yīng)枚舉 ?2.2 聲明綁定參數(shù)注解 4.1 ThreadLocalUtil? 4.2? 自定義異常

    2024年02月14日
    瀏覽(19)
  • springboot aop 自定義注解形式

    springboot aop 自定義注解形式

    2024年01月25日
    瀏覽(18)
  • spring boot 使用AOP+自定義注解+反射實(shí)現(xiàn)操作日志記錄修改前數(shù)據(jù)和修改后對(duì)比數(shù)據(jù),并保存至日志表

    spring boot 使用AOP+自定義注解+反射實(shí)現(xiàn)操作日志記錄修改前數(shù)據(jù)和修改后對(duì)比數(shù)據(jù),并保存至日志表

    使用FieldMeta自定義注解,看個(gè)人業(yè)務(wù)自行覺得是否需要重新定義實(shí)體 實(shí)現(xiàn)類 :通過該實(shí)現(xiàn)類獲取更新前后的數(shù)據(jù)。 該實(shí)現(xiàn)類的實(shí)現(xiàn)原理為:獲取入?yún)⒊鋈氲膇d值,獲取sqlSessionFactory,通過sqlSessionFactory獲取selectByPrimaryKey()該方法,執(zhí)行該方法可獲取id對(duì)應(yīng)數(shù)據(jù)更新操作前后的數(shù)

    2024年01月23日
    瀏覽(28)
  • 【SpringBoot】AOP 自定義注解的使用詳解

    ? ? ? ? Spring 中的切面 Aspect,這是 Spring 的一大優(yōu)勢(shì)。面向切面編程往往讓我們的開發(fā)更加低耦合,也大大減少了代碼量,同時(shí)呢讓我們更專注于業(yè)務(wù)模塊的開發(fā),把那些與業(yè)務(wù)無(wú)關(guān)的東西提取出去,便于后期的維護(hù)和迭代。 ????????AOP 的全稱為 Aspect Oriented Programming,

    2024年02月05日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包