千萬級資料並行如何處理?進入學習
推薦學習:
快取雪崩
是指大量的請求無法命中Redis
中的快取資料,也就是在Redis
找不到資料了,那業務系統只能到資料庫中查詢,進而導致所有的請求都傳送到了資料庫。如下圖所示:
資料庫並不像Redis
能處理大量請求,由快取雪崩導致的請求激增必須會導致資料庫所在宕機,這樣勢必會影響業務系統,所以如果發生快取雪崩,對於業務系統肯定是致命的。
什麼情況下出現快取雪崩呢?總結起來有以下兩個方面的原因:
大量Redis
快取資料同時過期,導致所有的傳送到Redis
請求都無法命中資料,只能到資料庫中進行查詢。
Redis
伺服器宕機,所有請求都無法經Redis
來處理,只能轉向資料庫查詢資料。
針對導致快取雪崩的原因,有不同的解決方法:
針對大量快取隨機過期時間,解決方法就是在原始過期時間的基礎上,再加一個隨機過期時間,比如1到5分鐘之間的隨機過期時間,這樣可以避免大量的快取資料在同一時間過期。
而針對Redis
解決宕機的導致的快取雪崩,可以提前搭建好Redis
的主從伺服器進行資料同步,並設定哨兵機制,這樣在Redis
伺服器因為宕機而無法提供服務時,可以由哨兵將Redis
從伺服器設定為主伺服器,繼續提供服務。
快取擊穿與快取雪崩的情況相似,雪崩是因為大量的資料過期,而快取擊穿則是指熱點資料過期,所有針對熱點資料的請求都需要到資料庫中進行處理,如下圖所示:
解決快取擊穿的三種方式:
如果我們能提前知道某個資料是熱點資料,那麼就可以不設定這些資料的過期,從而避免快取擊穿問題,比如一些秒殺活動的商品,在秒殺時會大量使用者存取,這時候我們就可以將這些用於秒殺的商品資料提前寫入快取並且不設定過期時間。
提前知道某些資料會有大量存取,我們當然可以設定不過期,但更多時候,我們並不能提前預知,這種情況要怎麼處理呢?
我們來分析一下快取擊穿的情況:
正常情況下,當某個Redis
快取資料過期時,如果有對該資料的請求,則重新到資料庫中查詢並再寫入快取,讓後續的請求可以命中該快取而無須再去資料庫中查詢。
而熱點資料過期時,由於大量請求,當某個請求無法命中快取時,會去查詢資料庫並重新把資料寫入Redis
,也就是在寫入Redis
之前,其他請求進來,也會去查詢資料庫。
好了,我們知道熱點資料過期後,很多請求會去查詢資料庫,那麼我們可以給去查詢資料庫的業務邏輯加個互斥鎖,只有獲得鎖的請求才能去查詢資料庫並把資料寫回Redis
,而其他沒有獲得鎖的請求只能等待資料就緒。
上述步驟的如下圖所示:
使用互斥鎖雖然可以非常簡單地解決快取擊穿問題,但沒有獲得鎖的請求雖然排隊等待,這樣影響了系統的效能,還有另一種解決快取擊穿的方法就是在業務資料冗餘一個過期時間,比如下面的資料中我們增加了expire_at
欄位用於表示資料過期時間。
{"name":"test","expire_at":"1599999999"}複製程式碼
登入後複製
這種方式的實現過程如下圖所示:
快取中的熱點資料中冗餘一個邏輯過期時間,但資料在Redis
不設定過期時間
當一個請求拿到Redis
中的資料時,判斷邏輯過期時間是否到期,如果沒有到期,直接返回,如果到期則開啟另一個執行緒獲得鎖後去查詢資料庫並將查詢的最新資料寫回Redis
,而當前請求返回已經查詢的資料。
快取穿透是指要查詢的資料既不在快取當中,也不在資料庫中,因為不在快取中,所以請求一定會到達資料庫,Redis
快取形同虛設,如下圖所示:
什麼條件下會發生快取穿透呢?主要有以下三種情況:
使用者惡意攻擊請求
誤操作把Redis
和資料庫裡的資料刪除了
使用者還未產生內容時,比如使用者的文章列表,使用者還未寫文章,所以快取和資料庫都沒有資料
當在Redis
快取中查詢不到資料時,再從資料庫查詢,如果同樣沒有資料,就直接快取一個空間或預設值,這樣可以避免下次再去查詢資料庫;不過為了防止之後已經資料庫已經相應資料庫,再返回空值問題,應該為快取設定過期時間,或者在產生資料時直接清除對應的快取空值。
雖然快取空值可以解決快取穿透問題,但仍然需要查詢一次資料庫才能確定是否有資料,如果有使用者惡意攻擊,高並行地使用系統不存在的資料id進行查詢,所有的查詢都要經過資料庫,這樣仍然會給資料庫帶來很大的壓力。
所以,有沒有不用查詢資料庫就能確定資料是否存在的辦法呢?有的,用布隆過濾器
。
布隆過濾器主要是兩個部分:bit陣列+N個雜湊函數,其原理為:
使用N個雜湊函數對所要標記的資料進行雜湊值計算。
將計算到的雜湊值對bit陣列的長度取模,這樣可以得到每個雜湊值在bit陣列的位置。
把bit陣列中對應的位置標記為1。
下面是布隆過濾器原理示意圖:
當要進行資料寫入時,執行述述步驟,計算對應bit陣列位置並標識為1,那麼在執行查詢時,就能查詢該資料是否存在了。
另外,由於雜湊碰撞問題導致的誤差,所以不存在的資料經過布隆過濾器後,會被判定為存在,再去查資料庫,不過雜湊碰到的概率很小,用布隆過濾器已經能幫我們攔截大部分的穿透請求了。
Redis
本身就支援布隆過濾器,所以我們可以直接使用Redis
布隆過濾器,而不用自己去實現,非常方便。
快取的雪崩、擊穿、穿透是在業務應用快取時經常會碰到的快取異常問題,其原因與解決方法如以下表示所示:
問題 | 原因 | 解決方法 |
---|---|---|
快取雪崩 | 大量資料過期或Redis 伺服器宕機 | 1. 隨機過期時間 2. 主從+哨兵的叢集 |
快取擊穿 | 熱點資料過期 | 1. 不設定過期時間 2. 加互斥鎖 3. 冗餘邏輯過期時間 |
快取穿透 | 請求資料庫和Redis 都沒有的資料 | 1. 快取空值或預設值 2. 布隆過濾器 |
推薦學習:
以上就是如何解決Redis快取雪崩、擊穿與穿透的詳細內容,更多請關注TW511.COM其它相關文章!