使用緩存須要瞭解幾個緩存問題,緩存擊穿、緩存穿透以及緩存雪崩,須要瞭解它們產生的緣由以及怎麼避免,尤爲是當你打算設計本身的緩存框架的時候須要考慮如何處理這些問題。git
通常的緩存系統,都是按照 key 去緩存查詢,若是不存在對應的 value ,就應該去後端系統查找(好比數據庫)。若是 key 對應的 value 是必定不存在的,而且對該 key 併發請求量很大,就會對後端系統就會形成很大的壓力。github
在高併發下,多線程同時查詢同一個資源,若是緩存中沒有這個資源,那麼這些線程都會去後端服務或數據庫查找,對數據庫形成極大壓力,緩存也就失去存在的意義。算法
緩存擊穿解決方案數據庫
致使緩存擊穿的問題在於高併發多線程情景下,許多請求一會兒都到後端服務和數據庫,致使後端服務與數據庫的壓力驟增。後端
處理這個問題,在多線程請求同一個 key 的時候,進行排隊,這樣第一次請求後端服務和數據庫以後更新緩存的值,下一個請求從緩存中取數據的時候就會拿到緩存數據,不會再請求後端服務和數據庫。緩存
緩存穿透是指用戶查詢數據,在數據庫沒有,天然在緩存中也不會有。這樣就致使用戶查詢的時候,在緩存中找不到,每次都要去數據庫中查詢,從而失去了緩存的意義並且相比直接查詢數據庫還增長了每次都去查緩存。服務器
緩存穿透解決方案數據結構
致使問題出現的緣由在於請求一個不存在的數據從而使得緩存始終不存在進而致使後端系統(主要是數據庫)要承受很大的壓力,因此想要解決這個問題,就勢必就在緩存這裏攔截住大量的請求,使得最終走到後端系統,查詢數據庫的請求儘量的少。多線程
通常處理這個問題,緩存不存在的時候會在緩存中設置一個時間較短的內容爲空的緩存,從而減小實際請求到後端和進行數據庫查詢的次數。
複雜一些的解決方案有 布隆過濾器,基本原理是設置一個 list,查詢緩存的時候從 list 裏進行判斷,這裏不作多介紹。
布隆過濾器(Bloom Filter)是1970年由布隆提出的。它其實是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器能夠用於檢索一個元素是否在一個集合中。它的優勢是空間效率和查詢時間都遠遠超過通常的算法,缺點是有必定的誤識別率和刪除困難
若是想要判斷一個元素是否是在一個集合裏,通常想到的是將全部元素保存起來,而後經過比較肯定。鏈表,樹等等數據結構都是這種思路. 可是隨着集合中元素的增長,咱們須要的存儲空間愈來愈大,檢索速度也愈來愈慢(O(n),O(logn))。不過世界上還有一種叫做散列表(又叫哈希表,Hash table)的數據結構。它能夠經過一個Hash函數將一個元素映射成一個位陣列(Bit array)中的一個點。這樣一來,咱們只要看看這個點是否是1就能夠知道集合中有沒有它了。這就是布隆過濾器的基本思想。
當緩存服務器重啓或者大量緩存集中在某一個時間失效,這樣在失效的時候,也會給後端系統和數據庫帶來很大壓力.
緩存雪崩解決方案
致使出現緩存雪崩的根本緣由在於緩存大量失效,從而致使大量請求沒有命中緩存,大量請求走到後端服務和數據庫,形成壓力。
若是系統啓動就依賴不少緩存,那能夠經過其它服務進行緩存預熱,提早把須要的數據放到緩存中,避免系統啓動大量請求直接請求到後端服務和數據庫。
既然是因爲同一時間緩存大量失效,咱們也能夠着手從緩存的失效時間上,作一些優化,讓緩存不要在同一時間點失效。
具體的實施辦法,你能夠在設置失效時間的時候隨機加幾秒過時時間,避免同一時間點緩存大量失效。
Contact me: weihanli@outlook.com