1. 程式人生 > 其它 >快取雪崩、擊穿、穿透

快取雪崩、擊穿、穿透

怎麼理解快取雪崩? 舉個簡單的例子:如果所有首頁的Key失效時間都是12個小時,中午13點重新整理的,我零點有個秒殺活動大量使用者湧入,假設當時每秒6000個請求,本來快取在可以抗住每秒5000個請求,但是快取當時所有的Key都失效了。此時1秒6000個請求全部落資料庫,資料庫必然扛不住,它會報警一下,真實情況可能DBA都沒反應過來就直接掛了。此時,如果沒有什麼特別的方案來處理這個故障,DBA很著急,重啟資料庫,但是資料庫立馬又被新的流量給打死了。 怎麼處理快取雪崩? 處理快取雪崩簡單,在批量往Redis存資料的時候,把每個Key的實效時間都加上一個隨機值就好了,這樣可以保證資料不會在同一時間大面積實效。 setRedis(Key,value,time + Math.random()* 10000) 如果Redis是叢集部署,將熱點資料均勻分佈在不同的redis庫中也能避免全部失效的問題。 或者設定熱點資料永遠不過期,有更新操作就更新快取就好了(比如運營更新了首頁商品,那你重新整理下快取就完事,不要設定過期時間)。 怎麼理解快取穿透? 快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷髮起請求,我們的資料庫的id都是1開始自增上去的,如發起id為-1的資料或id為特別大不存在的資料。這時的使用者可能是攻擊者,攻擊會導致資料庫壓力過大,嚴重會擊垮資料庫。 像這種你如果不對引數做校驗,資料庫id都是大於0的,我一直用小於0的引數請求,每次都能繞開Redis直接打到資料庫,資料庫也查不到,每次都這樣,併發高點就容易崩掉了。 1、快取穿透在介面層增加校驗,比如使用者鑑權校驗,引數做校驗,不合法的引數直接Return。 2、從快取取不到的資料,在資料庫中也沒有取到,這時也可以將對應的Key的value寫為null、未知錯誤、稍後重試這樣的值,具體取啥問產品或者看具體的場景,快取有效時間可以設定短點,如30秒(設定太長會導致正常情況也無法使用)。 3、布隆過濾器,對於惡意攻擊,向伺服器請求大量不存在的資料造成的資料穿透,還可以使用布隆過濾器先做一次過濾,對於不存在的資料布隆過濾器一般都能夠過濾掉,不讓請求再往後端傳送。當布隆過濾器說某個值存在時,這個值可能不存在,當它說不存在時,那就肯定不存在。 4、這樣可以防止攻擊使用者反覆用同一個id暴力攻擊,但是我們要知道正常使用者是不會在單秒內發起這麼多請求的,那閘道器層nginx也記得有配置項,可以讓運維對單個IP每秒訪問次數超出閾值的IP都拉黑。 怎麼理解快取擊穿? 至於快取擊穿嘛,這個跟快取雪崩有點像,但是又有一點不一樣,快取雪崩是因為大面積的快取失效,打崩了DB,而快取擊穿是指一個Key非常熱點,在不停的扛著大併發,大併發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大併發就穿破快取,直接請求資料庫,就像在一個完好無損的桶上鑿開了一個洞。 快取擊穿的話,設定熱點資料永不過期,或者加上互斥鎖就能搞定。