前言
歡迎各位進羣973961276一塊兒聊聊技術吹吹牛,每週都會有幾回抽獎送專業書籍的活動,獎品雖不甚值錢,但也算個彩頭不是
linux
我是Redis
你好,我是Redis,一個叫Antirez的男人把我帶到了這個世界上。c++
提及個人誕生,跟關係數據庫MySQL還挺有淵源的。算法
在我還沒來到這個世界上的時候,MySQL過的很辛苦,互聯網發展的愈來愈快,它容納的數據也愈來愈多,用戶請求也隨之暴漲,而每個用戶請求都變成了對它的一個又一個讀寫操做,MySQL是苦不堪言。尤爲是到「雙11」、「618「這種全民購物狂歡的日子,都是MySQL受苦受難的日子。數據庫
據後來MySQL告訴我說,其實有一大半的用戶請求都是讀操做,並且常常都是重複查詢一個東西,浪費它不少時間去進行磁盤I/O。後端
後來有人就琢磨,是否是能夠學學CPU,給數據庫也加一個緩存呢?因而我就誕生了!緩存
出生不久,我就和MySQL成爲了好朋友,咱們倆經常攜手出如今後端服務器中。服務器
應用程序們從MySQL查詢到的數據,在我這裏登記一下,後面再須要用到的時候,就先找我要,我這裏沒有再找MySQL要。網絡
爲了方便使用,我支持好幾種數據結構的存儲:數據結構
String架構
Hash
List
Set
SortedSet
Bitmap
······
由於我把登記的數據都記錄在內存中,不用去執行慢如蝸牛的I/O操做,因此找我要比找MySQL要省去了很多的時間呢。
可別小瞧這簡單的一個改變,我可爲MySQL減輕了不小的負擔!隨着程序的運行,我緩存的數據愈來愈多,有至關部分時間我都給它擋住了用戶請求,這一下它可樂得悠閒自在了!
有了個人加入,網絡服務的性能提高了很多,這都歸功於我爲數據庫捱了很多槍子兒。
零基礎和大三大四的朋友看這裏>>c/c++ 企業級項目實戰
已經工做了想繼續自我提高跳槽漲薪的工程師看這裏>>c/c++ linux服務器高級架構師學習
技術問題加我WeChat:lingshengxy免費諮詢,有時間會一一回答
緩存過時 && 緩存淘汰
不過很快我發現事情不妙了,我緩存的數據都是在內存中,但是就算是在服務器上,內存的空間資源仍是頗有限的,不能無節制的這麼存下去,我得想個辦法,否則吃棗藥丸。
不久,我想到了一個辦法:給緩存內容設置一個超時時間,具體設置多長交給應用程序們去設置,我要作的就是把過時了的內容從我裏面刪除掉,及時騰出空間就好了。
超時時間有了,我該在何時去幹這個清理的活呢?
最簡單的就是按期刪除,我決定100ms就作一次,一秒鐘就是10次!
我清理的時候也不能一口氣把全部過時的都給刪除掉,我這裏面存了大量的數據,要全面掃一遍的話那不知道要花多久時間,會嚴重影響我接待新的客戶請求的!
時間緊任務重,我只好隨機選擇一部分來清理,能緩解內存壓力就好了。
就這樣過了一段日子,我發現有些個鍵值運氣比較好,每次都沒有被個人隨機算法選中,每次都能倖免於難,這可不行,這些長時間過時的數據一直霸佔着很多的內存空間!氣抖冷!
我眼裏可揉不得沙子!因而在原來按期刪除的基礎上,又加了一招:
那些原來逃脫我隨機選擇算法的鍵值,一旦遇到查詢請求,被我發現已經超期了,那我就毫不客氣,當即刪除。
這種方式由於是被動式觸發的,不查詢就不會發生,因此也叫惰性刪除!
但是,仍是有部分鍵值,既逃脫了個人隨機選擇算法,又一直沒有被查詢,致使它們一直逍遙法外!而於此同時,可使用的內存空間卻愈來愈少。
並且就算退一步講,我可以把過時的數據都刪除掉,那萬一過時時間設置的很長,還沒等到我去清理,內存就吃滿了,同樣要吃棗藥丸,因此我還得想個辦法。
我苦思良久,終於憋出了個大招:內存淘汰策略,這一次我要完全解決問題!
我提供了8種策略供應用程序選擇,用於我遇到內存不足時該如何決策:
noeviction:返回錯誤,不會刪除任何鍵值
allkeys-lru:使用LRU算法刪除最近最少使用的鍵值
volatile-lru:使用LRU算法從設置了過時時間的鍵集合中刪除最近最少使用的鍵值
allkeys-random:從全部key隨機刪除
volatile-random:從設置了過時時間的鍵的集合中隨機刪除
volatile-ttl:從設置了過時時間的鍵中刪除剩餘時間最短的鍵
volatile-lfu:從配置了過時時間的鍵中刪除使用頻率最少的鍵
allkeys-lfu:從全部鍵中刪除使用頻率最少的鍵
有了上面幾套組合拳,我不再用擔憂過時數據多了把空間撐滿的問題了~
緩存穿透 && 布隆過濾器
個人日子過的還挺舒坦,不過MySQL大哥就沒我這麼舒坦了,有時候遇到些煩人的請求,查詢的數據不存在,MySQL就要白忙活一場!不只如此,由於不存在,我也無法緩存啊,致使一樣的請求來了每次都要去讓MySQL白忙活一場。我做爲緩存的價值就沒獲得體現啦!這就是人們常說的緩存穿透。
這一來二去,MySQL大哥忍不住了:「唉,兄弟,能不能幫忙想個辦法,把那些明知道不會有結果的查詢請求給我擋一下」
這時我想到了個人另一個好朋友:布隆過濾器
我這位朋友別的本事沒有,就擅長從超大的數據集中快速告訴你查找的數據存不存在(悄悄告訴你,個人這位朋友有一點不靠譜,它告訴你存在的話不能全信,其實有多是不存在的,不過它他要是告訴你不存在的話,那就必定不存在)。
若是你對我這位朋友感興趣的話,能夠看看這裏《白話布隆過濾器BloomFilter》。
我把這位朋友介紹給了應用程序,不存在的數據就沒必要去叨擾MySQL了,輕鬆幫忙解決了緩存穿透的問題。
緩存擊穿 && 緩存雪崩
這以後過了一段時間太平日子,直到那一天···
有一次,MySQL那傢伙正優哉遊哉的摸魚,忽然一大堆請求給他懟了過去,給他打了一個措手不及。
一陣忙活以後,MySQL怒氣衝衝的找到了我,「兄弟,咋回事啊,怎麼一會兒來的這麼猛」
我查看了日誌,趕忙解釋到:「大哥,實在很差意思,剛剛有一個熱點數據到了過時時間,被我刪掉了,不巧的是隨後就有對這個數據的大量查詢請求來了,我這裏已經刪了,因此請求都發到你那裏來了」
「你這乾的叫啥事,下次注意點啊」,MySQL大哥一臉不高興的離開了。
這一件小事我也沒怎麼放在心上,隨後就拋之腦後了,卻沒曾想幾天以後竟捅了更大的簍子。
那一天,又出現了大量的網絡請求發到了MySQL那邊,比上一次的規模大得多,MySQL大哥一下子功夫就給幹趴下了好幾回!
等了好半天這一波流量纔算過去,MySQL才緩過神來。
「老弟,這一次又是什麼緣由?」,MySQL大哥累的沒了力氣。
「這一次比上一次更不巧,這一次是一大批數據幾乎同時過了有效期,而後又發生了不少對這些數據的請求,因此比起上一次這規模更大了」
MySQL大哥聽了眉頭一皺,「那你卻是想個辦法啊,三天兩頭折磨我,這誰頂得住啊?」
「其實我也很無奈,這個時間也不是我設置的,要不我去找應用程序說說,讓他把緩存過時時間設置的均勻一些?至少別讓大量數據集體失效」
「走,咱倆一塊兒去」
後來,我倆去找應用程序商量了,不只把鍵值的過時時間隨機了一下,還設置了熱點數據永不過時,這個問題緩解了很多。哦對了,咱們還把這兩次發生的問題分別取了個名字:緩存擊穿和緩存雪崩。
咱們終於又過上了溫馨的日子···
彩蛋
那天,我正在努力工做中,不當心出了錯,整個進程都崩潰了。
當我再次啓動後,以前緩存的數據全都沒了,暴風雨似的請求再一次全都懟到了MySQL大哥那裏。
唉,要是我可以記住崩潰前緩存的內容就行了···
預知後事如何,請關注後續精彩······