1. 程式人生 > >關於redis快取資料庫的一些思考

關於redis快取資料庫的一些思考

#### 今晚無聊,躺在床上,在刷技術文章時,看見了一篇關於redis快取的文章 寫的蠻好,這也就引起了我對於redis思考! 不如往深了說 引起了我對於追求探索技術本質的一些思考 平時在網上刷到很多關於redis的文章,我也在專案中經常用到redis這個快取資料庫 記得自己初學redis時 總是糾結技術如果去學 但是隨著閱歷以及學習能力和經驗的提高 自己也對技術也有一些悟出來的道理 或者說是如何學好技術 往後有時間或者哪天心血來潮了寫一篇關於自己對於技術的認知 還是進入主題,在網上經常刷到關於redis的文章,自己也經常在專案中用到redis,但是自己從來沒有太過深究redis,心裡老覺得不得勁 於是今晚就心血來潮了寫一篇關於自己對redis的一些思考 這裡我就不說redis是幹什麼的了,如果不知道看下我之前寫的redis文章,這些文章中也有官網的內容 因為我也是從官網學的) #### 1.聊聊redis快取穿透問題 如何理解快取穿透呢?就是當請求訪問過來時 先去查詢redis快取,如果快取中沒有, 再去查詢mysql資料庫, 然後mysql資料庫返回資料到redis快取中, redis接收資料並把資料儲存起來, 這樣當下次請求過來時,服務端就直接查詢redis快取了並返回給客戶端,不必再去查詢mysql,緩解了資料庫壓力,並提高了效率 這是我們的正常情況對不對! ![正常情況](https://img-blog.csdnimg.cn/20210311011251104.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NzZG4xODc0MDU5OTA0Mg==,size_16,color_FFFFFF,t_70) 但但但但但但但是......有沒有想過一個問題,如果是黑客惡意攻擊,客戶端發起的請求中的資料,我們快取中不僅沒有,就連我們的mysql中也沒有! **這下完犢子了** 這下客戶端只要重複的傳送這個請求,所有的請求會經過redis後然後再來請求我們的mysql,因為我們資料庫中沒有呀,所以查詢不到,也沒有資料往redis中存),這就是快取穿透 那麼如果是一個黑客惡意發起請求,mysql就有可能在長時間內持續承受大量的請求,mysql這時候心裡很苦,很快就會撂挑子不幹了,直接宕機,(接下來,整個系統宕機,然後你就抓緊刪庫跑路吧,(逃, 如果是大型專案的話,這個損失是很大的 那我們就要像羔羊一樣任人宰割嗎?NONONO,redis還有一個好兄弟,**這個好兄弟叫作布隆過濾器** 這個好兄弟可以存放大資料量,(偷偷告訴你,存放大資料量是他的優點,但是他也有缺點,就是查詢到的結果不一定準確,0代表一定沒有,1代表不一定有,布隆過濾器這位redis的好兄弟我這裡就不介紹了,只介紹這位好兄弟如何仗義行俠幫助我們的redis 在中間加了這位好兄弟,那麼當請求進來後,會首先經過我們的布隆過濾器,這個好兄弟先判斷這個資料存不存在,若判斷不存在直接丟棄請求,若這個資料存在再去進行redis查詢,然後執行下一步,最後響應,有了這位好兄弟,我們就可以講資料庫中所有的查詢條件,放入布隆過濾器中,所有的請求先交給這位好兄弟來處理(這位好兄弟是有那麼一點不靠譜,但是大體上並不影響 ![布隆過濾器](https://img-blog.csdnimg.cn/20210311020519810.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NzZG4xODc0MDU5OTA0Mg==,size_16,color_FFFFFF,t_70) 其實還有一種解決方案是把查詢到的空值的key快取起來並設定過期時間,但是會有一種弊端,就是如何發起大量的請求,那豈不是要接收多少空值的key,都要存在redis中,redis是記憶體資料庫,記憶體不要錢嗎?而且遭到惡意攻擊,能有多大記憶體和黑客剛呢? **具體場景具體用法:** 1. 如果空值的key少可以考慮快取起來 2. 如果空值的key多並且不重複,還是讓布隆過濾器這位好兄弟來拔刀相助比較好 #### 2.聊聊redis快取雪崩問題 快取雪崩可以這樣理解,雪崩雪崩嘛!這些快取就像雪一樣發生了崩塌,快取是存在於我們的redis這位好兄弟這裡的,這位好兄弟平常管理著這些快取,加入哪一天這兄弟不高興了,撒手不幹了,宕機),那豈不是這些快取資料又沒了,當請求來臨時又要mysql兄弟處理了,mysql兄弟看到這麼些請求過來淦它,心裡直髮怵啊!簡直是瑟瑟發抖,造成了結果就是資料庫崩潰,系統崩潰 這就是我們快取雪崩,簡單來說redis宕機了 ![快取雪崩問題](https://img-blog.csdnimg.cn/20210311022303604.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NzZG4xODc0MDU5OTA0Mg==,size_16,color_FFFFFF,t_70) 解決方案也很簡單,簡單粗暴,一個不行來倆甚至更多,一節更比六節強,搭建redis叢集然後交給hystrix來監控 ![叢集](https://img-blog.csdnimg.cn/20210311024325516.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NzZG4xODc0MDU5OTA0Mg==,size_16,color_FFFFFF,t_70) #### 3.聊聊快取擊穿問題 快取擊穿這個和快取穿透字面上有點像,但是區別在於快取穿透是資料中沒有這個key,但是快取擊穿是資料中有這個key,並且我們要把這個key快取到redis中, 比如淘寶雙11,並不是所有的商品都要搞活動,只是一部分搞活動,那麼這一部分商品在活動開始時,必然會有大量的使用者去搶購,大量的請求),這時候如果我們的資料在mysql中,mysql必然不幹了,mysql這位兄弟記憶體又要罵娘了,那麼我們就需要redis來救場,提前把這些熱點的key(需要搞活動的商品)快取到redis中,當活動開始時直接去淦redis,沒事redis扛得住,這樣就解決了這個問題 但但但但但但是.......如果這個key突然在使用者還沒搶購完的時候,很媽離譜就過期了!那麼完犢子,mysql又要罵娘了 這就是快取擊穿(熱點key過期問題) 解決方案: 1. 熱點key竟然要媽離譜過期,我們在設定熱點key時讓這個bi永不過期就完事了,簡單粗暴 2. 互斥鎖,當第一個查詢資料庫的請求發起時,給快取中這個資料上鎖,其他請求這個key等待,當第一個查詢資料庫打請求完成後解鎖,其他請求直接從緩