日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2025/3/21 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 厉害了,如何通过双 key 来解决缓存并发问题? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來源公眾號:IT人的職場進階

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

我們在使用緩存的時候,不管Redis或者是Memcached,基本上都會遇到以下3個問題:緩存穿透、緩存并發、緩存集中失效。這篇文章主要針對【緩存并發】問題展開討論,并給出具體的解決方案。

1.什么是緩存并發?

在高并發的訪問下,當某個緩存處于過期失效的時間點時,極有可能出現多個進程同時查詢該緩存(該緩存是業務場景中非常 "熱點" 的數據,比如首頁的緩存數據)。因為查詢DB并重新緩存需要一定的時間,而瞬時并發非常高,如果此時緩存失效了,這些并發請求都會直接訪問DB,從而導致DB服務器的CPU或者內存負載過高,服務能力下降甚至宕機,此問題即緩存并發問題。

緩存并發問題在微服務架構下凸顯更加嚴重,比如某個基礎服務A因為上述問題出現不可用,進而導致依賴A服務的B、C服務也不可用,而B服務的不可用又導致服務E、F不可用,不可用的服務就像滾雪球一樣越滾越大,最終導致系統出現嚴重故障,此現象我們稱之為雪崩效應。

注意緩存并發和緩存集中失效的區別在于:緩存并發指的是某一個熱點key的失效,而緩存集中失效則是一批key同時失效,兩者都可能導致雪崩問題。

2.如何解決?

針對該問題,存在以下三種解決方案:

  • 加鎖:在緩存失效后,通過加鎖的方式只允許一個線程查詢數據和寫緩存,其他線程如果發現有鎖就等待,等解鎖后再返回數據。該方案會造成部分請求等待。

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

  • 雙key:思路和方案2類似,不同的是雙key分別緩存過期時間(key-time)和緩存數據(key-data),其中(key-time)的緩存失效時間設置為短期(比如5min),(key-data)的緩存失效時間設置為長期(比如1天)。當第一個線程發現 key-time 過期不存在時,則先更新key-time,然后去查詢數據庫并更新key-data 的值;當其他線程來獲取數據時,雖然第一個線程還沒有從數據庫查詢完畢并更新緩存,但發現key-time存在,會直接讀取緩存的舊數據返回。和二級緩存的方案對比,該方案的緩存空間利用率高。

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

    1. 寫緩存的示例代碼

    public?static?boolean?set(String?key,?String?value,?int?seconds)?{Jedis?jedis?=?null;try?{jedis?=?jedisPool.getResource();if?(seconds?>?0){//?添加數據緩存,緩存有效時間?=?真實時間?+?1?天jedis.set(key,?seconds?+?60?*?60?*?24,?value);//?添加過期時間緩存,緩存有效時間?=?真實時間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();//?緩存過期?&&?獲取鎖成功,setnx:原子操作if?(jedis.setnx("lock_"?+?key,?System.currentTimeMillis()?+?"")?==?1)?{/***?將鎖的失效時間設為60s,在60s內若查詢數據庫成功,則更新鎖的失效時間=緩存時間*?如果60s內出現異常,則60s后第一個請求又會去訪問數據庫*?返回null表示沒有查詢到數據庫,外層代碼會通過數據庫獲取數據并設置緩存*/jedis.expire("lock_"?+?key,?60);return?null;}?else{//?緩存未過期或者緩存過期但獲取鎖失敗,?則返回舊數據return?jedis.get(key);}}?catch?(JedisException?e)?{if?(jedis?!=?null)?{returnBrokenResource(jedis);jedis?=?null;}?throw?e;}?finally?{if?(jedis?!=?null)?{returnResource(jedis);}} }

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。