應對快取擊穿的解決方法

2021-08-16 05:21:53 字數 1808 閱讀 9669

分析乙個資料是否適合快取,我們要從訪問頻率、讀寫比例、資料一致性等要求去分析.

在高併發下,多執行緒同時查詢同乙個資源,如果快取中沒有這個資源,那麼這些執行緒都會去資料庫查詢,對資料庫造成極大壓力,快取失去存在的意義.打個比方,資料庫是人,快取是防彈衣,子彈是執行緒,本來防彈衣是防止子彈打到人身上的,但是當防彈衣裡面沒有防彈的物質時,子彈就會穿過它打到人身上.

方案一

後台重新整理

後台定義乙個job(定時任務)專門主動更新快取資料.比如,乙個快取中的資料過期時間是30分鐘,那麼job每隔29分鐘定時重新整理資料(將從資料庫中查到的資料更新到快取中).

方案二

檢查更新

將快取key的過期時間(絕對時間)一起儲存到快取中(可以拼接,可以新增新字段,可以採用單獨的key儲存..不管用什麼方式,只要兩者建立好關聯關係就行).在每次執行get操作後,都將get出來的快取過期時間與當前系統時間做乙個對比,如果快取過期時間-當前系統時間<=1分鐘(自定義的乙個值),則主動更新快取.這樣就能保證快取中的資料始終是最新的(和方案一一樣,讓資料不過期.)

方案三

分級快取

採用 l1 (一級快取)和 l2(二級快取) 快取方式,l1 快取失效時間短,l2 快取失效時間長。 請求優先從 l1 快取獲取資料,如果 l1快取未命中則加鎖,只有 1 個執行緒獲取到鎖,這個執行緒再從資料庫中讀取資料並將資料再更新到到 l1 快取和 l2 快取中,而其他執行緒依舊從 l2 快取獲取資料並返回。

方案四

加鎖方法1

// 方法1:

public synchronized list

<

string

> getdata01()

return result;

}

方法2
// 方法2:

static object lock = new object();

public listgetdata02()

}return result;

}

方法3
//方法3

public

list

<

string

> getdata03() }}

return result;

}

雙重判斷雖然能夠阻止高併發請求打到資料庫,但是第二個以及之後的請求在命中快取時,還是排隊進行的.比如,當30個請求一起併發過來,在雙重判斷時,第乙個請求去資料庫查詢並更新快取資料,剩下的29個請求則是依次排隊取快取中取資料.請求排在後面的使用者的體驗會不爽.

方法4

static lock reenlock = new reentrantlock();

public listgetdata04() throws interruptedexception finally

} else }}

return result;

}

當然,在實際分布式場景中,我們還可以使用 redis、tair、zookeeper 等提供的分布式鎖來實現.但是,如果我們的併發量如果只有幾千的話,何必殺雞焉用牛刀呢?

應對快取擊穿的解決方法

一.什麼樣的資料適合快取?分析乙個資料是否適合快取,我們要從訪問頻率 讀寫比例 資料一致性等要求去分析.二.什麼是快取擊穿 在高併發下,多執行緒同時查詢同乙個資源,如果快取中沒有這個資源,那麼這些執行緒都會去資料庫查詢,對資料庫造成極大壓力,快取失去存在的意義.打個比方,資料庫是人,快取是防彈衣,子...

快取擊穿的解決方法

摘抄自 在平常高併發的系統中,大量的請求同時查詢乙個 key 時,此時這個key正好失效了,就會導致大量的請求都打到資料庫上面去。這種現象我們稱為快取擊穿。解決辦法 上面的現象是多個執行緒同時去查詢資料庫的這條資料,那麼我們可以在第乙個查詢資料的請求上使用乙個 互斥鎖來鎖住它。其他的執行緒走到這一步...

redis雪崩,穿透,擊穿以及解決方法

一瞬間有大量的訪問只是資料庫崩了,比如12點重新整理快取,在重新整理快取的同時有大量的請求訪問,由於快取中沒有資料,知己查詢資料庫知識服務宕機 解決 往redis中存入快取的時候每個key設定失效時間的時候加乙個隨機數,使其不再同一時間大批量的重新整理快取 如在集群中部署熱點資料均勻分布,或者設定熱...