日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

厉害了,如何通过双 key 来解决缓存并发问题?

發(fā)布時(shí)間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 厉害了,如何通过双 key 来解决缓存并发问题? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

來(lái)源公眾號(hào):IT人的職場(chǎng)進(jìn)階

https://mp.weixin.qq.com/s/qOxTw4vT744ZjsJkc5HsEQ

我們?cè)谑褂镁彺娴臅r(shí)候,不管Redis或者是Memcached,基本上都會(huì)遇到以下3個(gè)問(wèn)題:緩存穿透、緩存并發(fā)、緩存集中失效。這篇文章主要針對(duì)【緩存并發(fā)】問(wèn)題展開(kāi)討論,并給出具體的解決方案。

1.什么是緩存并發(fā)?

在高并發(fā)的訪問(wèn)下,當(dāng)某個(gè)緩存處于過(guò)期失效的時(shí)間點(diǎn)時(shí),極有可能出現(xiàn)多個(gè)進(jìn)程同時(shí)查詢?cè)摼彺?#xff08;該緩存是業(yè)務(wù)場(chǎng)景中非常 "熱點(diǎn)" 的數(shù)據(jù),比如首頁(yè)的緩存數(shù)據(jù))。因?yàn)椴樵僁B并重新緩存需要一定的時(shí)間,而瞬時(shí)并發(fā)非常高,如果此時(shí)緩存失效了,這些并發(fā)請(qǐng)求都會(huì)直接訪問(wèn)DB,從而導(dǎo)致DB服務(wù)器的CPU或者內(nèi)存負(fù)載過(guò)高,服務(wù)能力下降甚至宕機(jī),此問(wèn)題即緩存并發(fā)問(wèn)題。

緩存并發(fā)問(wèn)題在微服務(wù)架構(gòu)下凸顯更加嚴(yán)重,比如某個(gè)基礎(chǔ)服務(wù)A因?yàn)樯鲜鰡?wèn)題出現(xiàn)不可用,進(jìn)而導(dǎo)致依賴A服務(wù)的B、C服務(wù)也不可用,而B(niǎo)服務(wù)的不可用又導(dǎo)致服務(wù)E、F不可用,不可用的服務(wù)就像滾雪球一樣越滾越大,最終導(dǎo)致系統(tǒng)出現(xiàn)嚴(yán)重故障,此現(xiàn)象我們稱之為雪崩效應(yīng)。

注意緩存并發(fā)和緩存集中失效的區(qū)別在于:緩存并發(fā)指的是某一個(gè)熱點(diǎn)key的失效,而緩存集中失效則是一批key同時(shí)失效,兩者都可能導(dǎo)致雪崩問(wèn)題。

2.如何解決?

針對(duì)該問(wèn)題,存在以下三種解決方案:

  • 加鎖:在緩存失效后,通過(guò)加鎖的方式只允許一個(gè)線程查詢數(shù)據(jù)和寫(xiě)緩存,其他線程如果發(fā)現(xiàn)有鎖就等待,等解鎖后再返回?cái)?shù)據(jù)。該方案會(huì)造成部分請(qǐng)求等待。

  • 二級(jí)緩存:A1為原始緩存,A2為拷貝緩存。A1失效時(shí),可以訪問(wèn)A2,其中A1的緩存失效時(shí)間設(shè)置為短期(比如5min),A2的緩存失效時(shí)間設(shè)置為長(zhǎng)期(比如1天)。如果緩存value很大,此方案的緩存空間利用率低。

  • 雙key:思路和方案2類似,不同的是雙key分別緩存過(guò)期時(shí)間(key-time)和緩存數(shù)據(jù)(key-data),其中(key-time)的緩存失效時(shí)間設(shè)置為短期(比如5min),(key-data)的緩存失效時(shí)間設(shè)置為長(zhǎng)期(比如1天)。當(dāng)?shù)谝粋€(gè)線程發(fā)現(xiàn) key-time 過(guò)期不存在時(shí),則先更新key-time,然后去查詢數(shù)據(jù)庫(kù)并更新key-data 的值;當(dāng)其他線程來(lái)獲取數(shù)據(jù)時(shí),雖然第一個(gè)線程還沒(méi)有從數(shù)據(jù)庫(kù)查詢完畢并更新緩存,但發(fā)現(xiàn)key-time存在,會(huì)直接讀取緩存的舊數(shù)據(jù)返回。和二級(jí)緩存的方案對(duì)比,該方案的緩存空間利用率高。

  • 3.雙key方案的示例代碼

    1. 寫(xiě)緩存的示例代碼

    public?static?boolean?set(String?key,?String?value,?int?seconds)?{Jedis?jedis?=?null;try?{jedis?=?jedisPool.getResource();if?(seconds?>?0){//?添加數(shù)據(jù)緩存,緩存有效時(shí)間?=?真實(shí)時(shí)間?+?1?天jedis.set(key,?seconds?+?60?*?60?*?24,?value);//?添加過(guò)期時(shí)間緩存,緩存有效時(shí)間?=?真實(shí)時(shí)間jedis.set("lock_"?+?key,?seconds,?System.currentTimeMillis()?+?"");}?else?{jedis.set(key,?value);jedis.set("lock_"?+?key,?System.currentTimeMillis()?+?"");}return?true;}?catch?(JedisException?e)?{if?(jedis?!=?null)?{returnBrokenResource(jedis);jedis?=?null;}throw?e;}?finally?{if?(jedis?!=?null)?{returnResource(jedis);}} }

    2. 讀緩存的示例代碼

    public?static?String?get(String?key)?{Jedis?jedis?=?null;try?{jedis?=?jedisPool.getResource();//?緩存過(guò)期?&&?獲取鎖成功,setnx:原子操作if?(jedis.setnx("lock_"?+?key,?System.currentTimeMillis()?+?"")?==?1)?{/***?將鎖的失效時(shí)間設(shè)為60s,在60s內(nèi)若查詢數(shù)據(jù)庫(kù)成功,則更新鎖的失效時(shí)間=緩存時(shí)間*?如果60s內(nèi)出現(xiàn)異常,則60s后第一個(gè)請(qǐng)求又會(huì)去訪問(wèn)數(shù)據(jù)庫(kù)*?返回null表示沒(méi)有查詢到數(shù)據(jù)庫(kù),外層代碼會(huì)通過(guò)數(shù)據(jù)庫(kù)獲取數(shù)據(jù)并設(shè)置緩存*/jedis.expire("lock_"?+?key,?60);return?null;}?else{//?緩存未過(guò)期或者緩存過(guò)期但獲取鎖失敗,?則返回舊數(shù)據(jù)return?jedis.get(key);}}?catch?(JedisException?e)?{if?(jedis?!=?null)?{returnBrokenResource(jedis);jedis?=?null;}?throw?e;}?finally?{if?(jedis?!=?null)?{returnResource(jedis);}} }

    總結(jié)

    以上是生活随笔為你收集整理的厉害了,如何通过双 key 来解决缓存并发问题?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。