天天看點

緩存穿透、緩存雪崩、緩存擊穿解決方法

緩存穿透:

  • 緩存穿透:查詢不存在的資料,不會寫入緩存,是以就會不斷的去查詢,在流量大的時候,資料庫可能就會挂了。
  • 解決方法:
    1. 布隆過濾器
    2. 将查詢結果為空的資料寫入緩存,設定過期時間短一些

緩存雪崩:

  • 緩存雪崩:大量的key設定了相同的過期時間,在某時刻全部失效,大量key請求資料庫,資料庫!雪崩!
  • 解決方法:在緩存過期時間上加一個随機值時間,使資料的過期時間分散,不在同一時刻失效

緩存擊穿:

  • 緩存擊穿:某些key在緩存将要過期的時候,碰巧有大量的并發請求這個key,這時緩存已過期,就會從資料庫查詢資料,大量的并發請求湧向資料庫,KO!資料庫敗!
  • 解決方法:
    1. 互斥鎖(mutex key):通路key之前,采用SETNX(set if not exists)設定鎖,來鎖住後邊資料的查詢,然後對這個key查詢資料庫并設定緩存,釋放鎖,其他資料查詢緩存

      特點:思路簡單,可以保持查詢結果一緻性,但:代碼複雜、可能死鎖、線程池阻塞。

    引用:

    業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作傳回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作傳回成功時,再進行load db的操作并回設緩存;否則,就重試整個get緩存的方法。

    SETNX,是「SET if Not eXists」的縮寫,也就是隻有不存在的時候才設定,可以利用它來實作鎖的效果”

    1. “提前”使用互斥鎖:

      設定逾時值,逾時值比實際資料過期的時間值小,當從緩存中讀到逾時值,立馬延長緩存的逾時值,然後讀取資料庫的資料并設定緩存

      特點:一緻性,缺點同互斥鎖

    2. 設定緩存“永不過期”:

      如果發現要過期了,背景異步,其他資料照樣輸出老的值,這條資料建構緩存:從庫裡更新資料到緩存,傳回結果

      特點:不會阻塞,但:查詢結果可能不一緻、每個值都要有逾時值,代碼複雜、多個值占用空間大

    3. 分級緩存:

      一級緩存、二級緩存,一級緩存失效時間短。

      先請求一級,如果一級失效未查詢到則加鎖,然後從資料庫讀取資料更新到一級、二級緩存中,在此期間,其他的資料請求二級緩存

      特點:不阻塞,但:會占用額外的緩存空間、查詢結果可能不一緻