有很多解決高併發的應用場景中都會使用memcache\redis快取來解決響應慢的問題,但是快取也不是萬能的,在使用方面有很多的考慮的問題,把快取比喻成防彈衣,但是如果你沒有穿好這件防彈衣會適得其反,下面我根據自己的理解就展開來談談。
在高併發場景下有乙個常常被忽略的乙個地方,讀多還是寫多,讀多寫少用快取,寫多讀少用佇列。
為什麼要用快取?為了系統的高效能,在每個系統的效能指標中有兩個重要的點,乙個是效能最佳點和效能最大值,超過最大融載值就走向系統崩潰的邊緣了。
快取穿透
快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,特別大不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。
解決方案:
1.在伺服器端,接收引數時業務介面中過濾不合法的值,null,負值,和空值進行檢測和空值。
2.bloom filter:類似於雜湊表的一種演算法,用所有可能的查詢條件生成乙個bitmap,在進行資料庫查詢之前會使用這個bitmap進行過濾,如果不在其中則直接過濾,從而減輕資料庫層面的壓力。
3.空值快取:一種比較簡單的解決辦法,在第一次查詢完不存在的資料後,將該key與對應的空值也放入快取中,只不過設定為較短的失效時間,例如幾分鐘,這樣則可以應對短時間的大量的該key攻擊,設定為較短的失效時間是因為該值可能業務無關,存在意義不大,且該次的查詢也未必是攻擊者發起,無過久儲存的必要,故可以早點失效。
快取雪崩
因為快取服務掛掉或者熱點快取失效,所有請求都去查資料庫,導致資料庫連線不夠或者資料庫處理不過來,從而導致整個系統不可用。
解決方案:
加鎖排隊、 設定過期標誌更新快取 、 設定過期標誌更新快取 、二級快取(引入一致性問題)、 預熱、 快取與服務降級。
1.執行緒互斥:只讓乙個執行緒構建快取,其他執行緒等待構建快取的執行緒執行完,重新從快取獲取資料才可以,每個時刻只有乙個執行緒在執行請求,減輕了db的壓力,但缺點也很明顯,降低了系統的qps。
快取擊穿
快取擊穿實際上是快取雪崩的乙個特例,快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由於併發使用者特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力。擊穿與雪崩的區別即在於擊穿是對於某一特定的熱點資料來說,而雪崩是全部資料。
解決方案:
1.快取設定不過期。
從redis上看,確實沒有設定過期時間,這就保證了,不會出現熱點key過期問題,也就是物理不過期。但是它會遇到乙個資料更新的問題,或者說資料不一致的問題。
在value中儲存過期時間,在編碼處理的時候,有條件(過期時間小於一分鐘)對快取資料進行更新,這個方案對效能最佳。
2.使用鎖工具(分布式鎖)
$redis
->
setnx
($key
,time()
+$expire);
# 加鎖
$redis
->
del(
$key);
# 解鎖
#新版本加鎖
#nx意思為set if not exist,即當key不存在時,我們進行set操作;
#若key已經存在,則不做任何操作;
#px意思是給這個key加乙個過期設定
$redis
->
set(
$resource
,$token,[
'nx'
,'px'
=>10]
);
總結:快取好比防彈衣,不意味著你穿上防彈衣就可以刀槍不入,只有更好的使用快取才會達到更好的作用,方案有很多,適合你的就是好的。 快取擊穿 快取穿透 快取雪崩區別
快取穿透 產生原因 當前端傳送一條請求 這條請求快取和資料庫都沒有 到後台,會先到快取裡找,沒有再到資料庫去找,也沒有,如果有人惡意攻擊會造成資料庫蹦了,這就是穿透 解決方法 不管前面發的請求後台有沒有資料,都給乙個相應的值,比如乙個 空字串,在存到redies中,這樣下次再來查就不會再到資料庫中去...
快取穿透 快取擊穿 快取雪崩
一 快取處理流程 前台請求,後台先從快取中取資料,取到直接返回結果,取不到時從資料庫中取,資料庫取到更新快取,並返回結果,資料庫也沒取到,那直接返回空結果。二 快取穿透 描述 快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為 1 的資料或id為特別大不存在的資料。這時的使...
快取穿透,快取擊穿,快取雪崩
所謂的快取穿透,簡單來講就是查詢某些不存在的key時,快取和資料庫查詢結果都為空,而空的結果又不被快取起來,而導致每次查詢都去請求資料庫層的情況。在流量大時,可能db就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。過程 快取不命中,進而導致每次查詢都去查詢資料庫,快取也就失去了作...