你們好,我是南橘,從接觸java到如今也有差很少兩年時間了,兩年時間,從一名連java有幾種數據結構都不懂超級小白,到如今懂了一點點的進階小白,學到了很多的東西。知識越分享越值錢,我這段時間總結(包括從別的大佬那邊學習,引用)了一些日常學習和麪試中的重點(自我認爲),但願給你們帶來一些幫助java
這篇文章的出現,首先要感謝一我的三太子敖丙 ,就是他的文章讓我發現,原來Redis的知識如此的多姿多彩。恩恩,他的文章,我是期期都看node
這是這篇文章的思惟導圖,由於用的是免費版的軟件,因此有很多水印,須要原版的能夠問我要程序員
Redis篇,由於時間和篇幅的緣由,並無一次性寫完,因而乎,分紅了上下兩篇,沒有看過上半部分的小夥伴能夠去看一下~面試
Redis基礎知識兩篇就知足(一)redis
這一次,從Redis最爲人津津樂道(面試也常常常問)的緩存三崩壞來講起算法
顧名思義,你們應該都見過雪崩,南橘我更是遠遠地親眼見過,那場景,很有種天崩地裂的感受,而對於數據庫來講,緩存雪崩,也說得上是一種天崩地裂了。 同一時間Redis緩存大面積失效,那一瞬間Redis跟不存在同樣,這個時候數據直接請求到數據庫。你想一想,緩存的意義就是減小DB,若是緩存沒有了,大量的請求還不直接打爆數據庫?數據庫
緩存雪崩如何出現的?數組
解決辦法:緩存
有一個Key很是熱點,在不停扛着大併發,大併發集中對這一點進行訪問,當這個Key失效的瞬間、大量併發擊穿緩存,直接訪問數據庫。bash
其實緩存擊穿,真的算不上什麼特別大的問題,畢竟不是每一個公司都在同一個Key上都有那麼大的熱點,只須要設置好過時時間,穩定好Redis集羣,緩存擊穿不難避免。
解決辦法:
在個人經驗來看,設置互斥鎖顯然沒有必要,一個熱點永不過時就能解決的問題,爲何還要用到鎖?這不是平白增長複雜度嗎?也許在特殊場景能看到,可是對於我這個小白來講,僅僅能在各位大牛的博客裏看到這個觀點。
從名字上來看,緩存擊穿和緩存穿透很像,實際上頁比較像,可是既然區分了出來,天然有一些不一樣的地方
緩存穿透的概念很簡單,用戶想要查詢一個數據,發現redis內存數據庫沒有,也就是緩存沒有命中,因而向持久層數據庫查詢。發現也沒有,因而本次查詢失敗。當用戶不少的時候,緩存都沒有命中,因而都去請求了持久層數據庫。這會給持久層數據庫形成很大的壓力,這時候就至關於出現了緩存穿透。
可是,緩存穿透真正要防止的是黑客。
若是一個黑客每次故意查詢一個在緩存內必然不存在的數據,致使每次請求都要去存儲層去查詢,這樣緩存就失去了意義。若是在大流量下數據庫可能掛掉,這也是緩存擊穿。 解決辦法:
利用布隆過濾器來防止緩存擊穿,主要是經過將已存在的緩存放到布隆過濾器中,當黑客訪問不存在的緩存時迅速返回避免緩存及DB掛掉。
布隆過濾器本質上布隆過濾器是一種數據結構,比較巧妙的機率型數據結構(probabilistic data structure),特色是高效地插入和查詢,能夠用來告訴你 「某樣東西必定不存在或者可能存在」。
布隆過濾器是由一個很長的bit數組和一系列哈希函數組成的。
數組的每一個元素都只佔1bit空間,而且每一個元素只能爲0或1。
布隆過濾器擁有k個哈希函數,當一個元素加入布隆過濾器時,會使用k個哈希函數對其進行k次計算,獲得k個哈希值,而且根據獲得的哈希值,在位數組中把對應下標的值置位1。
判斷某個數是否在布隆過濾器中,就對該元素進行k次哈希計算,獲得的值在位數組中判斷每一個元素是否都爲1,若是每一個元素都爲1,就說明這個值在布隆過濾器中。
當插入的元素愈來愈多時,當一個不在布隆過濾器中的元素,通過一樣規則的哈希計算以後,獲得的值在位數組中查詢,有可能這些位置由於其餘的元素先被置1了。
因此布隆過濾器存在誤判的狀況,可是若是布隆過濾器判斷某個元素不在布隆過濾器中,那麼這個值就必定不在。
經過這個方法,就能夠有效的防止黑客致使的緩存穿透了。
其實不是很傳統,只是我感受全部的集羣都有主從模式orz
主從模式的一個做用是備份數據,這樣當一個節點損壞(指不可恢復的硬件損壞)時,數據由於有備份,能夠方便恢復。 另外一個做用是負載均衡,全部客戶端都訪問一個節點確定會影響Redis工做效率,有了主從之後,查詢操做就能夠經過查詢從節點來完成。
在主從模式中,一個Master能夠有多個Slaves,默認配置下,master節點能夠進行讀和寫,slave節點只能進行讀操做,沒法進行寫操做。
若是修改默認配置,可讓slave進行寫,可是這毫無心義,由於寫入的數據不會同步給其餘slave,同時,master節點若是修改了,slave上的數據回立刻被覆蓋。
slave節點掛了不影響其餘slave節點的讀和master節點的讀和寫,從新啓動後會將數據從master節點同步過來。master節點掛了之後,不影響slave節點的讀,Redis將再也不提供寫服務,master節點啓動後Redis將從新對外提供寫服務。
因此,咱們能夠發現Redis的主從和Zookeeper的主從徹底不同!它居然不會選舉!
這個缺點影響是很大的,尤爲是對生產環境來講,是一刻都不能中止服務的,因此通常的生產壞境是不會單單隻有主從模式的。因此有了下面的sentinel模式。
哨兵模式要搭配主從模式來使用,主從不能本身選舉,那咱們就加一個哨兵,當sentinel發現master節點掛了之後,sentinel就會從slave中從新選舉一個master。
哨兵的做用就是監控Redis系統的運行情況。它的功能包括如下兩個。
(1)監控主服務器和從服務器是否正常運行。
(2)主服務器出現故障時自動將從服務器轉換爲主服務器。
複製代碼
這不就皆大歡喜了嗎?
哨兵的工做方式:
sentinel模式基本能夠知足通常生產的需求,具有高可用性。可是當數據量過大到一臺服務器存放不下的狀況時,主從模式或sentinel模式就不能知足需求了,這個時候須要對存儲的數據進行分片,將數據存儲到多個Redis實例中,這就是cluster模式。
cluster的出現是爲了解決單機Redis容量有限的問題,將Redis的數據根據必定的規則分配到多臺機器。
Redis-Cluster採用無中心結構,它的特色以下:
全部的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。
節點的失效是經過集羣中超過半數的節點檢測失效時才生效。
客戶端與redis節點直連,不須要中間代理層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可。
cluster能夠說是sentinel和主從模式的結合體,經過cluster能夠實現主從和master重選功能,因此若是配置三個副本三個分片的話,就需九六個Redis實例。 由於Redis的數據是根據必定規則分配到cluster的不一樣機器的,當數據量過大時,能夠新增機器進行擴容,這種模式適合數據量巨大的緩存要求,當數據量不是很大使用sentinel便可。
引用一張大佬的圖片來直觀展示一下什麼是 Redis-Cluster
每一個請求訪問Redis-Cluster集羣的時候,都會進行一個路由,路由能夠經過Hash(也能夠用別的)來進行隨機分片,可是若是徹底hash的話極可能致使分片們旱的旱死,澇的澇死。,因此,提出了**一致性哈希(自動緩存遷移)+虛擬節點(自動負載均衡)**的方法來解決問題
具體內容你們能夠看看這篇文章,寫的比較詳細,看的也很過癮
www.jianshu.com/p/49c9e03ee… 關於redis的幾件小事(十)redis cluster模式
![]()
一致性哈希的原理 :將全部master node落在一個圓環上面,而後,有一個key過來以後。一樣就是hash值,而後會用hash值在圓環對應的各個點上(每一個點都有一個hash值)去對比,看hash值落在那個位置,落在圓環上面之後,就會順時針旋轉去尋找距離本身最近的一個節點,數據的存儲於讀取都在該節點進行。
一致性哈希的優點 :保證了任何一個master宕機,只會影響以前在那個master上面的數據,由於照着順時針走,所有在以前的master上面找不到了,master也宕機了,就會繼續順着順時針走到下一個master節點去。這樣就只會有一部分數據丟失。
既然Redis能儲存數據,天然也就要刪除多餘的數據,否則,空間都被佔滿了,新的內容放在哪裏?聰明的程序員提出了三個辦法解決Redis的內存問題。
建立一個定時器,當key設置有過時時間,且過時時間到達時,由定時器任務當即執行對鍵的刪除操做,默認100ms就隨機抽一些key判斷是否過時,過時的話就刪除,用處理器性能換取存儲空間(拿時間換空間)
優勢:節約內存,到時就刪除,快速釋放掉沒必要要的內存佔用
缺點:CPU壓力很大,不管CPU此時負載量多高,均佔用CPU,會影響redis服務器響應時間和指令吞吐量
當Redis中的數據到了過時時間,咱們先不作處理。等下次訪問該數據時進行一次判斷,若是未過時,就正常返回,若是發現數據已過時,馬上刪除,而後返回不存在,用存儲空間換取處理器性能(拿空間換時間)
優勢:節約CPU性能,發現必須刪除的時候才刪除
缺點:內存壓力很大,出現長期佔用內存的數據
不知道你們不知道發現了沒有,大部分的算法,不是時間換空間,就是空間換時間。剛剛發現這個祕密的我簡直驚呆了,這就是人類的終極奧祕之一了,只要咱們知道這個訣竅,就能解決大部分的問題。
在Redis的redis.config文件中還可經過搜索maxmemory-policy來設置淘汰機制
noeviction:當內存使用達到閾值的時候,全部引發申請內存的命令會報錯。
allkeys-lru:在主鍵空間中,優先移除最近未使用的key。
volatile-lru:在設置了過時時間的鍵空間中,優先移除最近未使用的key。
allkeys-random:在主鍵空間中,隨機移除某個key。
volatile-random:在設置了過時時間的鍵空間中,隨機移除某個key。
volatile-ttl:在設置了過時時間的鍵空間中,具備更早過時時間的key優先移除。
複製代碼
Redis篇寫完了,感受Redis真的是有好多內容啊,以前以爲本身貌似全都掌握了同樣,回過頭來,發現仍是有不少不懂~~~~~很開心能在這裏給你們分享個人收穫,我知道個人技術棧比起各位響噹噹的大佬仍是有差距,可是人不努力怎麼知道本身不能夠?但願你們能喜歡個人文章,也但願這篇文章能幫到你們。
同時須要思惟導圖的話,能夠聯繫我,畢竟知識越分享越香!
![]()