最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

30w+數(shù)據(jù)使用RedisTemplate?pipeline空指針NullPointerException異常分析

 更新時(shí)間:2023年08月31日 09:10:57   作者:我不是碼農(nóng)  
這篇文章主要為大家介紹了30w+數(shù)據(jù)使用RedisTemplate?pipeline空指針NullPointerException異常分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

為了實(shí)現(xiàn)布控預(yù)警的業(yè)務(wù)需求,在flink流式處理時(shí)查詢r(jià)edis進(jìn)行比對(duì),然后方案是放在redis里的數(shù)據(jù)格式為Set,key使用的直接是布控對(duì)象的值,比如身份證號(hào)、車牌號(hào)、手機(jī)號(hào)、imsi碼等等,然后value的值為該布控對(duì)象所屬的任務(wù)ID,之所以是這樣設(shè)計(jì),是因?yàn)榭赡苡卸鄠€(gè)任務(wù)都設(shè)置了該布控對(duì)象,這時(shí)候比對(duì)到了該布控對(duì)象,會(huì)根據(jù)任務(wù)id查詢對(duì)應(yīng)的策略進(jìn)行不同的業(yè)務(wù)處理。

目前一個(gè)任務(wù)的布控對(duì)象的數(shù)據(jù)量批量插入20w+的數(shù)據(jù)到redis中,數(shù)據(jù)量比較大,所以用到了pipe,在使用過程中發(fā)生了錯(cuò)誤,發(fā)生了NullPointerException異常,進(jìn)行了排查記錄如下

首先debug代碼

偽代碼就是

redisTemplate.executePipeLined(connection -> {
    objectives.parallelStream().forEach(obj -> {
        connection.setCommands().sAdd(rawKey,rawValue);
    });
})

objectives是所有布控對(duì)象,這里我用到了并行流(后面我改成串行就沒報(bào)錯(cuò)了,原因后面講),代碼是沒啥問題的,然后報(bào)錯(cuò)地方是執(zhí)行完上述邏輯后,執(zhí)行connection.closePipeLine()里的result.getResultHolder()該result是null,發(fā)現(xiàn)了異常,為啥list元素里會(huì)是空的呢,原來lettuce的pipe是初始化一個(gè)arraylist進(jìn)行存儲(chǔ)的,而我外面是一個(gè)并行流,相當(dāng)于是并發(fā)調(diào)用connection.setCommands().sAdd()->pipe.add(),是這里發(fā)生了并發(fā)操作list的錯(cuò)誤導(dǎo)致的。

我自己寫了一個(gè)測(cè)試用例,并行流調(diào)用arraylist.add,然后去遍歷里面的元素,也是會(huì)報(bào)元素為空導(dǎo)致的NullPointerException

沒想到啊,雖然lettuce底層是共享一個(gè)鏈接,使用的是netty的異步模型,不過也防止不了開發(fā)人員在外面是并發(fā)操作這個(gè)命令啊,lettuce是線程安全的庫,但是這個(gè)LettuceConnection是spring這邊實(shí)現(xiàn)的,結(jié)果來這一出...bug蠻多的,之前用spring-data-jpa那塊分頁也有點(diǎn)問題,模塊太多了,依賴多個(gè)庫之后配置多了可能spring的開發(fā)人員都弄不清關(guān)系了,給他們提了一個(gè)bug

https://github.com/spring-projects/spring-data-redis/issues/2653

調(diào)試分析

接上面,我在調(diào)試的時(shí)候,pipe里有些返回值error是command timed out after 10 seconds,這就是原因,執(zhí)行redis命令超時(shí)了,為啥會(huì)超時(shí)呢,由于我使用的是Lettuce的redis客戶端庫(最后發(fā)現(xiàn)就是這個(gè)庫的原因),我開始自己調(diào)試,不調(diào)試不要緊,一調(diào)試震驚了,我在上面的forEach循環(huán)里打斷點(diǎn),結(jié)果發(fā)現(xiàn)執(zhí)行一個(gè)sAdd就會(huì)立即把值flush推到redis服務(wù)器,馬上就生效了。

這說明lettuce的pipe根本就是個(gè)擺設(shè),于是進(jìn)去sAdd()看了一下,在DefaultEndpoint.write()方法里有個(gè)autoFlushCommands為true,所以其實(shí)每次sAdd()都會(huì)直接flush到服務(wù)器而不是添加到緩沖區(qū)buffer。

這里不得不說一下原因了,lettuce底層使用的是netty,是一個(gè)異步非阻塞(通過Future-Listener機(jī)制實(shí)現(xiàn)異步事件,網(wǎng)絡(luò)IO使用的是同步非阻塞IO,即NIO)的線程和請(qǐng)求/響應(yīng)模型(一般情況是不需要禁用自動(dòng)刷新的,可見官網(wǎng)說明),所以我們才會(huì)在上面報(bào)command timed out after 10 seconds時(shí)沒拋出來這個(gè),因?yàn)槭褂玫氖莕etty的future每個(gè)請(qǐng)求都是異步的。

這個(gè)錯(cuò)誤是lettuce拋出來的,因?yàn)閚etty的異步模型,所以lettuce會(huì)給每個(gè)command(Future)設(shè)置一個(gè)ScheduleFuture定時(shí)任務(wù),時(shí)間為timeout,里面的邏輯是如果command到時(shí)間了還沒isDone()就會(huì)設(shè)置一個(gè)超時(shí)異常。

后面看了官網(wǎng)文檔,其實(shí)建議我們用默認(rèn)的自動(dòng)flush就行了,我于是做了下對(duì)比,先把超時(shí)時(shí)間改大點(diǎn),不讓拋異常,然后比較性能,并行流因?yàn)橛衎ug,所以這里我用反射把pipe的List實(shí)現(xiàn)arraylist改成了線程安全的list,并進(jìn)行測(cè)試

我的布控對(duì)象測(cè)試數(shù)據(jù)解析后大概key有28w

實(shí)現(xiàn)方式耗時(shí)線程安全的list
并行流關(guān)閉自動(dòng)flush平均10.08/s
并行流開啟自動(dòng)flush平均9.16/s
串行流關(guān)閉自動(dòng)flush平均15.36/s平均16.20/s
串行流開啟自動(dòng)flush平均6.74/s平均8.06/s

可以看到官網(wǎng)推薦的自動(dòng)每次執(zhí)行就flush的性能更高些

lettuce設(shè)置timeout超時(shí)時(shí)間,spring.redis.timeout,我之前設(shè)置的是10s,可以自行調(diào)整
lettuce設(shè)置pipe的禁用自動(dòng)刷新,這里需要重新構(gòu)造LettuceConnectionFactory,然后設(shè)置PipelingFlushPolicy

我在官網(wǎng)找到了說明https://lettuce.io/core/release/reference/#_pipelining_and_co...里面也說明了pipe默認(rèn)每個(gè)命令在發(fā)出后都寫入傳輸?shù)脑?,有興趣的可以看看

以上就是30w+數(shù)據(jù)使用RedisTemplate pipeline空指針NullPointerException異常分析的詳細(xì)內(nèi)容,更多關(guān)于RedisTemplate pipeline空指針異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Spring實(shí)現(xiàn)自定義錯(cuò)誤信息返回詳解

    基于Spring實(shí)現(xiàn)自定義錯(cuò)誤信息返回詳解

    這篇文章主要為大家詳細(xì)介紹了如何基于Spring實(shí)現(xiàn)自定義錯(cuò)誤信息返回效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • 帶你重新認(rèn)識(shí)Java動(dòng)態(tài)代理

    帶你重新認(rèn)識(shí)Java動(dòng)態(tài)代理

    這篇文章主要為大家介紹了Java的動(dòng)態(tài)代理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • 詳解Java?token主流框架之JWT

    詳解Java?token主流框架之JWT

    JWT(JSON?Web?Token)是一種基于JSON格式的輕量級(jí)的、用于身份認(rèn)證的開放標(biāo)準(zhǔn),它通過在用戶和服務(wù)器之間傳遞一個(gè)安全的、可靠的、獨(dú)立的JSON對(duì)象來進(jìn)行身份驗(yàn)證和授權(quán),本文將詳細(xì)給大家介紹Java?token主流框架之JWT,需要的朋友可以參考下
    2023-05-05
  • java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實(shí)戰(zhàn)

    java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實(shí)戰(zhàn)

    這篇文章主要介紹了java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用,結(jié)合實(shí)例形式分析了java枚舉類的定義、構(gòu)造及相關(guān)應(yīng)用操作技巧,需要的朋友可以參考下
    2019-08-08
  • java異常:異常處理--try-catch結(jié)構(gòu)詳解

    java異常:異常處理--try-catch結(jié)構(gòu)詳解

    今天小編就為大家分享一篇關(guān)于Java異常處理之try...catch...finally詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2021-09-09
  • Java如何從Redis中批量讀取數(shù)據(jù)

    Java如何從Redis中批量讀取數(shù)據(jù)

    這篇文章主要介紹了Java如何從Redis中批量讀取數(shù)據(jù)的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • SpringBoot integration實(shí)現(xiàn)分布式鎖的示例詳解

    SpringBoot integration實(shí)現(xiàn)分布式鎖的示例詳解

    常規(guī)項(xiàng)目都是采用Redission來實(shí)現(xiàn)分布式鎖,進(jìn)行分布式系統(tǒng)中資源競(jìng)爭(zhēng)加鎖操作,偶然發(fā)現(xiàn)SpringBoot中的integration也實(shí)現(xiàn)多種載體的分布式鎖控制,下面我們就來看看具體實(shí)現(xiàn)方法吧
    2023-12-12
  • Java并發(fā)編程之LockSupport類詳解

    Java并發(fā)編程之LockSupport類詳解

    LockSupport是一種線程阻塞工具,它可以在線程內(nèi)任意位置讓線程阻塞.接下來就帶著大家詳細(xì)了解一下LockSupport類,,需要的朋友可以參考下
    2021-05-05
  • 在springboot中使用AOP進(jìn)行全局日志記錄

    在springboot中使用AOP進(jìn)行全局日志記錄

    這篇文章主要介紹就在springboot中使用AOP進(jìn)行全局日志記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java數(shù)據(jù)庫連接池的幾種配置方法(以MySQL數(shù)據(jù)庫為例)

    Java數(shù)據(jù)庫連接池的幾種配置方法(以MySQL數(shù)據(jù)庫為例)

    這篇文章主要介紹了Java數(shù)據(jù)庫連接池的幾種配置方法(以MySQL數(shù)據(jù)庫為例) 的相關(guān)資料,需要的朋友可以參考下
    2016-07-07

最新評(píng)論

维西| 万州区| 沁水县| 高雄县| 保康县| 砀山县| 阳西县| 工布江达县| 邵武市| 成武县| 麻城市| 封丘县| 阿拉善盟| 彭泽县| 阳曲县| 寻甸| 三亚市| 疏勒县| 宕昌县| 梨树县| 东乡族自治县| 阿巴嘎旗| 淄博市| 通海县| 大城县| 壤塘县| 三江| 阿克陶县| 休宁县| 江山市| 景德镇市| 九龙县| 郓城县| 新郑市| 富锦市| 白银市| 织金县| 吉安市| 阳城县| 缙云县| 旺苍县|