亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

我自己寫了一個(gè)測試用例,并行流調(diào)用arraylist.add,然后去遍歷里面的元素,也是會報(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í)了,為啥會超時(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就會立即把值flush推到redis服務(wù)器,馬上就生效了。

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

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

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

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

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

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

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

lettuce設(shè)置timeout超時(shí)時(shí)間,spring.redis.timeout,我之前設(shè)置的是10s,可以自行調(diào)整
lettuce設(shè)置pipe的禁用自動刷新,這里需要重新構(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空指針異常的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot?aop里的@Pointcut()的配置方式

    springboot?aop里的@Pointcut()的配置方式

    這篇文章主要介紹了springboot?aop里的@Pointcut()的配置方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • MybatisPlus逆向工程的項(xiàng)目實(shí)踐

    MybatisPlus逆向工程的項(xiàng)目實(shí)踐

    Mybatis-Plus逆向工程,是MP官方提供的一款代碼生成器,可以自動生成對應(yīng)的實(shí)體類、Mapper接口和配置文件,,本文主要介紹了MybatisPlus逆向工程的項(xiàng)目實(shí)踐,感興趣的可以了解一下
    2024-03-03
  • Spring boot配置多數(shù)據(jù)源代碼實(shí)例

    Spring boot配置多數(shù)據(jù)源代碼實(shí)例

    這篇文章主要介紹了Spring boot配置多數(shù)據(jù)源代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java面試應(yīng)用上線后Cpu使用率飆升如何排查

    java面試應(yīng)用上線后Cpu使用率飆升如何排查

    這篇文章主要為大家介紹了java面試中應(yīng)用上線后Cpu使用率飆升如何排查的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Spring Cloud詳解實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法

    Spring Cloud詳解實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法

    這篇文章主要介紹了Spring Cloud實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法,OpenFeign 是 Spring Cloud 家族的一個(gè)成員, 它最核心的作用是為 HTTP 形式的 Rest API 提供了非常簡潔高效的 RPC 調(diào)用方式,希望對大家有所幫助。一起跟隨小編過來看看吧
    2022-07-07
  • MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例

    MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例

    這篇文章主要介紹了MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Hibernate用ThreadLocal模式(線程局部變量模式)管理Session

    Hibernate用ThreadLocal模式(線程局部變量模式)管理Session

    今天小編就為大家分享一篇關(guān)于Hibernate用ThreadLocal模式(線程局部變量模式)管理Session,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • MyBatis中insert操作返回主鍵的實(shí)現(xiàn)方法

    MyBatis中insert操作返回主鍵的實(shí)現(xiàn)方法

    在使用MyBatis做持久層時(shí),insert語句默認(rèn)是不返回記錄的主鍵值,而是返回插入的記錄條數(shù)。這篇文章主要介紹了MyBatis中insert操作返回主鍵的方法,需要的朋友可以參考下
    2016-09-09
  • idea生成類注釋和方法注釋的正確方法(推薦)

    idea生成類注釋和方法注釋的正確方法(推薦)

    這篇文章主要介紹了idea生成類注釋和方法注釋的正確方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 詳解Huffman編碼算法之Java實(shí)現(xiàn)

    詳解Huffman編碼算法之Java實(shí)現(xiàn)

    Huffman編碼是一種編碼方式,常用于無損壓縮。本文只介紹用Java語言來實(shí)現(xiàn)該編碼方式的算法和數(shù)據(jù)結(jié)構(gòu)。有興趣的可以了解一下。
    2016-12-12

最新評論