如圖,乙個正常的請求一般都會經過cache層再到storage層,如果cache層沒有而在storage層查到,則將資料新增到cache層後返回,下次再有同樣的請求則直接從cache層返回資料,無需再請求storage層;而如果在storage層也獲取不到資料,則沒有資料新增到cache裡,下次再有同樣的請求會繼續到達storage層,這就是快取穿透的定義。
快取的乙個作用就是保護storage,也就是mysql之類的資料庫,而快取穿透的話就失去了這一層保護。
1、程式路由階段就限定id的範圍(譬如使用正則)
2、程式硬編碼判斷id值的合法性
3、資料庫查詢判斷等
假設有一張新聞表的id範圍是100到2000,這時如果查詢2004或者3000等id是沒有的,但不代表未來沒有。因此這裡有其中乙個做法(設定空鍵)如下:
1、譬如key=news2004,如果資料庫查詢返回空
2、那麼我們依然往redis儲存乙個我們約定好的資料結構並設定過期時間,譬如設定為200秒(到底多少秒要根據實際情況來調整)
3、下次如果繼續查到這個key,那麼我們增加這個key的過期時間(譬如5秒)
以下為「偽**」演示:
string newsid = getparameter("id");
news getnews = getfromredis("news" + newsid);
if(getnews == null)
settoredis(getnews,200); // 塞入redis,初始過期時間為200秒
}else if(getnews.equal(defaultcache()))
response.write(getnews);
接下來我們對以上方案進行一點優化,增加乙個防護手段(**單ip):
如果有惡意使用者進行反覆請求,那麼我們的redis裡很快就會塞滿各種無用的新聞key。數量過多,對資料庫也會有壓力(畢竟第一次還是要訪問資料庫的)
優化策略是:對於乙個ip,我們單獨開闢乙個key/value,key=字首+ip
1、如果db沒有命中,則 +2分
2、如果命中「預設值」, +1分
3、一旦有以上操作,對應key的資料重新expire指定的時間(譬如3600秒)
4、當該ip的分數值達到我們設定的閾值(譬如6分),則讓該ip無法正常訪問我們的新聞頁面(或者給乙個靜態頁面,類似於404預設頁)
譬如有乙個ip 192.168.10.20,我們將其塞入了快取,但是一些稍微專業的「惡意使用者」會更換ip,用192.168.10.9、192.168.10.8、192.168.10.101等繼續惡搞。
對於這種情況我們需要設定封禁ip列表(**ip段),譬如192.168.10開頭的ip一律不能訪問。redis可用列表(list)解決這個問題,乙個列表最多可以包含 2^32 - 1 個元素 (4294967295, 每個列表超過40億個元素)。
布隆過濾器是一種比較巧妙的概率型資料結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你 「某樣東西一定不存在或者可能存在」。
相比於傳統的 list、set、map 等資料結構,它更高效、占用空間更少,但是缺點是其返回的結果是概率性的,而不是確切的。
適用於精確性要求不嚴格的場景,如上面的黑白名單、是否簽到等。業務流程如下:
快取穿透和快取擊穿處理
為了應對越來越大的流量,快取便成為系統服務必不可少的一部分,但使用快取就會出現快取擊穿和快取穿透的威脅。背景介紹 網際網路應用逐步深入到生活的各個角落,為了滿足越來越多使用者使用網際網路應用的需求,幾乎所有網際網路公司都採用快取的方案來解決瞬時流量超高,或者長期流量過高的問題。但使用快取存在風險 快...
redis 快取穿透 快取雪崩處理方案
一 快取穿透 什麼是快取穿透 訪問某一key的時候,該key不在redis中,也不在db中,因此當非法使用者頻繁請求該key的時候,每一次請求,都直接穿過了redis,都最終落在的db上,從而造成宕機,影響整個系統,這種現象稱之為快取穿透 處理方案 二 快取雪崩 什麼是快取雪崩 每乙個key存在過期...
redis 快取穿透和快取擊穿處理
為了應對越來越大的流量,快取便成為系統服務必不可少的一部分,但使用快取就會出現快取擊穿和快取穿透的威脅。背景介紹 網際網路應用逐步深入到生活的各個角落,為了滿足越來越多使用者使用網際網路應用的需求,幾乎所有網際網路公司都採用快取的方案來解決瞬時流量超高,或者長期流量過高的問題。但使用快取存在風險 快...