快取
使用快取,出於兩個場景需要:高效能,高併發;計算機的業務資料,為了實現高可用和安全性,必然要進行持久化處理,但目前的技術而言, 持久化到硬碟或者從硬碟中查詢本來就是一件非常慢的事情,但實際我們又要求在大量的資料中快速訪問,所以,一般我們會把資料提前載入記憶體中,實現高效能訪問;而高效能意味著可以做到高併發。
雙寫一致性
只要用快取,就可能會涉及到快取與資料庫雙儲存雙寫,雙寫會有資料一致性的問題;
方案:序列化讀寫:序列化讀寫就是讀和寫都在乙個庫中操作,不做讀寫分離,序列化可以保證不會出現讀寫不一致情況,但效率會大大降低,通常涉及事務和鎖錶行等。所以如果業務不要求完全一致性,通常不要採取這樣的方案。
方案:最經典的快取+資料庫讀寫的模式,就是 cache aside pattern。
問題:為什麼是刪除快取,而不是更新快取?
1、在複雜點的快取場景,快取不單單是資料庫中直接取出來的值。
2、懶載入策略
問題:先刪快取,中間插入乙個查詢,又快取了舊的值,最後更新資料庫,問題就出現了,快取和資料庫長時間不一致,怎麼辦?
這是乙個同步問題,如果用鎖解決就太過麻煩了,比較好的是利用mq非同步化這兩個請求,同時保證他們的執行順序,就可以保證快取和資料庫必然一致,考慮具體業務的時候,還可以做更多的優化,比喻允許非強一致性,可以發了獲取快取請求後,就去資料庫取乙個舊值來用一會。
快取雪崩
問題:對於系統 a,假設每天高峰期每秒 5000 個請求,本來快取在高峰期可以扛住每秒 4000 個請求,但是快取機器意外發生了全盤宕機。快取掛了,此時 1 秒 5000 個請求全部落資料庫,資料庫必然扛不住,它會報一下警,然後就掛了。此時,如果沒有採用什麼特別的方案來處理這個故障,dba 很著急,重啟資料庫,但是資料庫立馬又被新的流量給打死了。這就是快取雪崩。
方案:快取雪崩的事前事中事後的解決方案如下。
快取穿透
問題:對於系統a,假設一秒 5000 個請求,結果其中 4000 個請求是黑客發出的惡意攻擊。
黑客發出的那 4000 個攻擊,快取中查不到,每次你去資料庫里查,也查不到。
舉個栗子。資料庫 id 是從 1 開始的,結果黑客發過來的請求 id 全部都是負數。這樣的話,快取中不會有,請求每次都「視快取於無物」,直接查詢資料庫。這種惡意攻擊場景的快取穿透就會直接把資料庫給打死。
方案:解決方式很簡單,每次系統 a 從資料庫中只要沒查到,就寫乙個空值到快取裡去,比如set -999 unknown
。然後設定乙個過期時間,這樣的話,下次有相同的 key 來訪問的時候,在快取失效之前,都可以直接從快取中取資料。
方案:布隆過濾器(bloom filte),這個就是乙個bitmap和hash結合的演算法,可以保證存在的資料一定會被判別為存在;所以把所有的key放到過濾器中,查詢的時候如果發現不存在,那一定是不存在的key,如果發現是存在的key,也有可能該key不存在,再配合方案1,這樣就不可能會被快取穿透。
快取擊穿:
問題:快取擊穿,就是說某個 key 非常熱點,訪問非常頻繁,處於集中式高併發訪問的情況,當這個 key 在失效的瞬間,大量的請求就擊穿了快取,直接請求資料庫,就像是在一道屏障上鑿開了乙個洞。
方案:簡單粗暴,可以將熱點資料設定為永遠不過期;
方案:其實擊穿也是乙個同步問題,同步問題的解決方案可以使用 redis or zookeeper 實現互斥鎖,等待第乙個請求構建完快取之後,再釋放鎖,進而其它請求才能通過該 key 訪問資料。
高併發 快取
開闢乙個新的資料交換區,以解決原始資料獲取代價太大的問題,讓資料得到更快的訪問。問題1 快取雪崩 問題2 資料不一致 現象 資料發生更新時,db和快取的資料不一致,多個快取副本的資料不一致。原因 更新發生異常 策略 快取更新失敗後加入重試佇列 ttl縮短 問題3 hotkey 原因 微博數百萬使用者...
高併發架構
1 高併發中一些概念 1.pv 訪問量 頁面訪問量,頁面重新整理一次算一次。2.uv 獨立訪客 即unique visitor,乙個客戶端 電腦,手機 為乙個訪客 3.dau 日活躍使用者數 登入或使用了某個產品的使用者數,這與流量統計工具裡的訪客 uv 概念相似。4.峰值qps 原理 每天80 的...
高併發快取實現
private static concurrenthashmap gloddeptfutumap new concurrenthashmap future 介面允許表示已經完成的任務 正在執行過程中的任務或者尚未開始執行的任務。futuretask 類實現了 future,幷包含一些建構函式,允許將...