一、快取雪崩
很多時候,Redis中的快取是要設定過期時間的,假如Redis中的資料,過期時間都設定成一樣的,那么到了時間之后,全部快取過期失效,下一秒所有的請求都會訪問資料庫,那么資料庫可能因為訪問量過大導致“崩潰”,這就是快取雪崩,
如果快取集中在一段時間內失效,發生大量的快取穿透,所有的查詢都落在資料庫上,造成了快取雪崩,
這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布,大多數系統設計者考慮用加鎖或者佇列的方式保證快取的單執行緒(行程)寫,從而避免失效時大量的并發請求落到底層存盤系統上,
應對方法:
1、快取永遠不過期:最暴力的解決辦法,快取不設定自動過期時間,只要快取不崩,資料庫就不會崩,
2、使用加鎖或者佇列的方式保證來保證不會有大量的執行緒對資料庫一次性進行讀寫,從而避免失效時大量的并發請求落到底層存盤系統上,
加鎖排隊. 限流-- 限流演算法. 1.計數 2.滑動視窗 3. 令牌桶Token Bucket 4.漏桶 leaky bucket [1],
在快取失效后,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量,比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待,
3、做二級快取,或者雙快取策略,
A為原始快取,B為拷貝快取,A失效時,可以訪問B,快取A的失效時間為20分鐘,快取B不設定失效時間,自己做快取預熱操作,細分以下幾個小點:
- 從快取A讀資料庫,有則直接回傳,
- 若快取A沒有資料,直接從B讀資料,直接回傳,并且異步啟動一個更新執行緒,
- 更新執行緒同時更新快取A和快取B,
4、給快取的失效時間,加上一個隨機值,避免集體失效,讓快取過期時間不那么一致,比如一批快取資料24小時后過期,那么就在這個基礎上,每條快取的過期時間前后隨機1-6000秒(1-10分鐘),設定不同的過期時間,讓快取失效的時間點盡量均勻,
二、快取擊穿
快取擊穿跟快取雪崩有點像,但是又有一點不一樣,快取雪崩是因為大面積的快取失效,打崩了DB,而快取擊穿不同的是快取擊穿是指一個Key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大并發就穿破快取,直接請求資料庫,就像在一個完好無損的桶上鑿開了一個洞,
應對方法:
1、設定熱點資料永遠不過期,或者加上互斥鎖就能搞定了,
https://www.lizenghai.com/archives/27853.html
https://mp.weixin.qq.com/s?__biz=MzUxNDA1NDI3OA==&mid=2247484581&idx=2&sn=54f2306012619e3dbe36c4fcf9493039&chksm=f94a854cce3d0c5a8be0825de18d381b388d247a7a2145759c3818cfcfa28a364bf8b8b38383&mpshare=1&scene=23&srcid=0627JwWmdlo4tdChETfgpSBL#rd
三、快取穿透
很多專案在使用Redis或其他快取框架的時候,都是先查詢快取,查詢不到的話再查詢資料庫,查到之后再放到快取(記憶體)中;如果一個key值本身就不存在,那么每一次都會查詢資料庫,也就是常說的【快取穿透】,簡單理解就是先去快取中找不到,再去資料庫查詢,在資料庫中也找不到,就發生了快取穿透,
key對應的資料在資料源并不存在,每次針對此key的請求從快取獲取不到,請求都會到資料源,從而可能壓垮資料源,比如用一個不存在的用戶id獲取用戶資訊,不論快取還是資料庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮資料庫,
快取穿透是指查詢一個一定不存在的資料,由于快取是不命中時需要從資料庫查詢,查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到資料庫去查詢,造成快取穿透,資料在redis不存在,資料庫也不存在,回傳空,一般來說空值是不會寫入redis的,如果反復請求同一條資料,那么則會發生【快取穿透】,
應對方法:
1、快取空物件
如果在Redis中查詢不到,并且查詢資料庫也沒有結果,那么就將這個key設定一個空值(value=https://www.cnblogs.com/liuhaidon/p/空),同時寫入到Redis中,并設定一個超時過期時間,例如五分鐘,那么五分鐘以內對這個key的所有查詢就可以攔截下來,就不會訪問資料庫了,如果資料庫有key對應的資料了,那么五分鐘后Redis中的快取過期,會訪問資料庫并加載快取;但是如果被惡意攻擊,每次請求的key都不相同且在資料庫中也是不存在的,那么依然會發生快取穿透,會穿透到資料庫,
如果一個資料庫查詢回傳的資料為空,我們仍然把這個空結果進行快取,但它的過期時間會很短,最長不超過五分鐘,快取空物件會有兩個問題:
- 空值做了快取,意味著快取層中存了更多的鍵,需要更多的記憶體空間 ( 如果是攻擊,問題更嚴重 ),比較有效的方法是針對這類資料設定一個較短的過期時間,讓其自動剔除,
- 快取層和存盤層的資料會有一段時間視窗的不一致,可能會對業務有一定影響,例如過期時間設定為 5分鐘,如果此時存盤層添加了這個資料,那此段時間就會出現快取層和存盤層資料的不一致,此時可以利用訊息系統或者其他方式清除掉快取層中的空物件,
2、布隆過濾器
將可能存在的資料Hash到一個足夠大的bitmap上,它可以告訴你 “某個key一定不存在或者可能存在”,一個一定不存在的資料會被bitmap攔截,
四、快取并發
大多數時候,我們的程式訪問Redis都不可能是單執行緒,那么當多個Client并發對Redis進行set key操作的時候,可能會產生一些問題;其實Redis本身是單執行緒的,這種時候會按照先后順序進行操作;或者把操作放在佇列中,按順序執行;
但比如這種情況:
1.token過期,有兩個執行緒都去重新獲取token;
2.執行緒1獲取到token1;
3.執行緒2獲取到token2,此時token1過期;
4.執行緒1把token1放到Redis,再拿著token1去呼叫服務,發現過期了,繼續去請求token3,此時token2過期;
5.執行緒2把token2放到Redis,再拿著token2去呼叫服務,發現過期了,繼續去請求token4,此時token3過期;
6.... ...
這就需要我們在更新快取的時候,做一些控制了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/1136.html
標籤:NoSQL
上一篇:分布式快取Memcached
下一篇:Redis常用命令
