您好,登錄后才能下訂單哦!
今天小編給大家分享一下Redis中熱點key存儲問題怎么解決的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
緩存穿透、緩存擊穿和緩存雪崩都是因為緩存中數據不存在,導致走數據庫去查詢數據。
由于緩存數據不存在,所有的請求都會走到數據庫,因此會導致數據庫的壓力過大甚至出現服務崩潰,導致整個系統無法使用。
定義:緩存穿透是由于客戶端求的數據在緩存中不存在,然后去查詢數據庫,然而數據庫沒有客戶端要查詢的數據,導致每一次請求都會走數據庫查詢操作。真正的問題在于該數據本身就是不存在的
。
舉例:客戶端請求商品詳情信息時,攜帶一個商品ID,此時該商品ID是不存在的(不管是緩存中還是數據庫中)。導致每一次請求該ID商品的數據信息都會走數據庫。
危害:由于請求的參數對應的數據根本不存在,會導致每一次都會請求數據庫,增加數據庫的壓力或者服務崩潰,更有甚至影響到其他的業務模塊。經常發生在用戶惡意請求
的情況下會發生。
解決方案:
1、根據請求的參數緩存一個null值。并且為該值設置一個過期時間,可以將時間設置短暫一點。
2、使用布隆過濾器,首先通過布隆過濾器進行篩選,如果在過濾器中存在則去查詢數據庫,然后添加到緩存中。如果不存在則直接返回客戶端數據不存在。
3、由于緩存穿透可能是用戶發起惡意請求,可以將用戶ip給記錄下來,針對惡意的ip請求進行封禁。
方案分析:
第一種方案,針對不存在的key,會緩存一個空的值。假設這樣的請求特別多,是否都會一一去設置一個空值的緩存,此時Redis中就存在大量無效的緩存空值。假設這樣的key是商品或者文章類的ID,我們在設置空值之后,如果后臺添加數據應該去更新ID對應的緩存值,并設置一個合理的過期時間。
第二種方案,也是業界使用最多的一種方案。布隆過濾器的優點在于基于Redis實現,內存操作并且底層的實現也是非常節約內存。 當后臺添加數據成功時,將該數據的ID添加到布隆過濾器中,前端在請求時先走布隆過濾器進行驗證是否存在。但布隆過濾器也存在一個弊端,就是hash沖突問題。這里的hash沖突是什么意思呢?就是說多個ID在進行hash計算時,得到的hash位都是同一個值,這就導致在驗證是否存在時誤判。本身是有的,得到的結果是沒有。布隆過濾器的一個弊端就是,它說有并不一定有,它說沒有就一點是沒有的。
第三種方案,針對同一用戶一段時間內發起大量的請求,觸發緩存穿透機制,此時我們可以顯示該客戶端的訪問。但攻擊者如果是發起DDOS這樣的攻擊,是沒法完全的避免此類攻擊,因此這種方案不是一個很好的解決方案。
方案總結:
我們首先在請求層面增加第3中方案,做一個限流機制、IP黑名單機制,控制一些惡意的請求,如果是誤判我們可以實現IP解封這樣的操作。在緩存層則使用第1中方案實現。設置一個合理的緩存時間。
對于能容忍誤判的業務場景,可以直接才用第2中方案實現。完全基于Redis,減少了系統的復雜度。
定義:緩存擊穿是因為某個熱點key不存在,導致走數據庫查詢。增加了數據庫的壓力。這種壓力可能是瞬間的,也可能是比較持久的。真正的問題在于該key是存在,只是緩存中不存在,導致走數據庫操作
。
舉例:有一個熱門的商品,用戶查看商品詳情時攜帶商品的ID以獲取到商品的詳情信息。此時緩存中的數據已經過期了,因此來的所有請求都要走數據庫去查詢。
危害:相對緩存穿透而言,該數據在數據庫中是存在的,只是因為緩存過期了,導致要走一次數據庫,然后在添加到緩存中,下次請求就能正常走緩存。所謂的危害同樣的還是針對數據庫層面的危害。
解決方案:
1、加互斥鎖。針對第一個請求,發現緩存中沒有數據,此時查詢數據庫添加到緩存里面。這樣后面的請求就不需要走數據庫查詢。
2、增加業務邏輯過期時間。在設置緩存時,我們可以添加一個緩存過期時間。每次去讀取的時候,做一個判斷,如果這個過期時間與當前時間小于一個范圍,觸發一個后臺線程,去數據庫拉取一下數據,接著更新一下緩存數據和緩存的過期時間。其實原理就是代碼層面給緩存延長緩存時長。
3、數據預熱。實現通過后臺把數據添加到緩存里面。例如秒殺場景開始前,就把商品的庫存添加到緩存里面,這樣用戶請求來了之后,就直接走緩存。
4、永久不過期。在給緩存設置過期時間時,讓它永久不過期。后臺單獨開啟一個線程,來維護這些緩存的過期時間和數據更新。
方案分析:
互斥鎖保證了只有一個請求走數據庫,這是一個優點。但是對于分布式的系統,得才用分布式鎖實現,分布式鎖的實現本身就有一定的難點,這樣提升了系統的復雜度。
第2種方案,利用Redis不過期,業務過期的方案實現。保證了每一次請求都能拿到數據,同時也可以做到一個后臺線程去更新數據。缺點在于后臺線程沒有更新完數據,此時請求拿到的數據是舊數據,可能對應實時性要求高的業務場景存在弊端。
第3種方案,使用緩存預熱每次加載都走緩存,與第2種方案差不多。不過也存在熱點數據更新問題,因此該方案適合數據實時性要求不高的數據。
第4中方案,和第2、3種方案類似,在此基礎上進行了一定優化,使用后臺異步線程主動去更新緩存數據。難點在于更新的頻率控制。
方案總結:
對于實時性要求高的數據,推薦使用第1種方案,雖然在技術上有一定的難度但是能做到數據的實時性處理。如果發生某些請求等待時間久,可以返回異常,讓客戶端重新發送一次請求。
對于實時性要求不高的數據,可以使用第4種方案。
定義:前面在說到緩存擊穿,是因為緩存中的某個熱點key失效,導致大量請求走數據庫。然而緩存雪崩其實也是同樣的道理,只不過這個更嚴重而已,是大部分緩存的key失效,而不是一個或者兩個key失效。
舉例:在一個電商系統中,某一個分類下的商品數據在緩存中都失效了。然而當前系統的很多請求都是該分類下面的商品數據。這樣就導致所有的請求都走數據庫查詢。
危害:由于一瞬間大量的請求涌入,每一個請求都要走數據庫進行查詢。數據庫瞬間流量涌入,嚴重增加數據庫負擔,很容易導致數據庫直接癱瘓。
解決方案:
1、緩存時間隨機。因為某一時間,大量的緩存失效,說明緩存的過期時間比較集中。我們直接將過期的時間設置為不集中,隨機打亂。這樣緩存過期時間相對不會很集中,就不會出現同一時刻大量請求走數據庫進行查詢操作。
2、多級緩存。不單純的靠Redis來做緩存,我們也可以使用memcached來做緩存(這里只是舉一個例子,其他的緩存服務也可以)。緩存數據時,對Redis做一個緩存,對memcached做一個緩存。如果Redis失效了,我們可以走memcached。
3、互斥鎖。緩存擊穿中我們提到了使用互斥鎖來實現,同樣我們也可以用在雪崩的情況下。
4、設置過期標志。其實也可以用到緩存擊穿中講到的永久不過期。當請求時,判斷過期時間,如果臨近過期時間則設置一個過期標志,觸發一個獨立的線程去對這個緩存進行更新。
方案分析:
第1種方案采用隨機數緩存時間,能保證key的失效時間分散。難點在于如何設置緩存時間,如果對于一些需要設置短緩存時間并數據量非常大的數據,該方案就需要合理的控制時間。
第2種方案使用多級緩存,可以保證請求全部走緩存數據。但這樣增加了系統的架構難度,以及其他的各種問題,例如緩存多級更新。
第3種方案使用互斥鎖,在緩存擊穿中我們提到了互斥鎖,在雪崩的場景中我們雖然能使用,但是這樣會產生大量的分布式鎖。
第4種方案使用邏輯緩存時間,很好的保證了系統的緩存壓力。
方案總結:
在實際的項目中推薦使用第1、2和4種方案試下會更好一些。
以上就是“Redis中熱點key存儲問題怎么解決”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。