❝哨兵主要針對單節點故障無法自動復原的解決方案,叢集主要針對單節點容量、並發問題、線性可擴充性的解決方案。本文使用官方提供的redis cluster。文末有你們想要的設定ssh背景哦!
❞
#❝咔噠整理了一個路線圖,打造一份面試寶典,準備按照這樣的路線圖進行編寫文章,後期發現沒有補充到的知識點在進行添加。也期待各位夥伴一起來幫忙補充一下。評論區見哦!❞
那麼我們就需要把單機的主從改為多對多的方式並且所有的主節點都會連結在一起互相溝通。這樣的方式既可以分擔單機內存,也可以分發請求,提高系統的可用性。
如圖:當有大量請求寫入時,不再會單一的向一個主節點發送指令,而會把指令進行分流到各個主節點,達到分擔記憶體、避免大量請求的作用。
那麼指令是如何進行分流儲存的呢!我們就需要到叢集儲存結構中一探究竟。
如何理解提高系統的可用性這句話,我們看下圖,當master1宕機後對系統的影響不會那麼大,仍然可以提供正常的服務。
這時候就會有人問了,當master1宕機後集群這個時候怎麼工作呀!這個問題會在下文的故障轉移來給你解答。並且在原理篇會對這個問題進行詳解
#單機的儲存是當用戶發起請求後直接把key儲存到自己的記憶體即可。 叢集的儲存結構就沒有那麼簡單了,首先當使用者發起一個key指令後需要做的事情。
那麼現在問題來了,這個key到底應該儲存在那個redis存儲空間裡邊呢!
其實redis在叢集啟動後就已經把儲存空間劃分了16384
份,每台主機保存一部分。
這裡要注意的是我給每個redis儲存空間裡邊的編號就相當於一個小的儲存空間(專業術語「哈希槽」
),你可以理解為一棟樓裡邊的編號,一棟樓就是redis的整個存儲空間,每個房子的編號就相當於一個存儲空間,這個存儲空間會有一定的區域來保存對應的key,並非上圖取模後的位置。
箭頭指向的28是指的28會存放在這個區域裡,而這個房子有可能會存放29、30、31等。
此時問題來了,如果新增、減少一台機器後怎麼辦呢!看圖說話,能用圖說明盡量不去用文字。
在新增一台機器後,會從其他三個儲存空間中拿出一定的槽分配給新的機器。這裡可以自己設定想給新的機器放多少個槽。
同樣減少一台機器後會把去掉的槽在重新分配給其它現有的機器跟新增節點一樣,可以指定節點接收槽。
所謂的增節點或去節點就是改變槽所儲存的位置不同。 了解了叢集的儲存結構後,我們就需要在對另一個問題進行說明了,叢集是如何設計內部通訊呢!來了一個值,取得一個key,去哪裡拿數據,跟著這個問題我們看下文。
#叢集中的每個節點會在一定的時期給其它節點發送ping訊息,其它節點返回pong作為回應。經過一段時間後所有節點都會知道叢集全部節點的槽資訊。
如下圖有三個節點,那麼就會把16384個雜湊槽分成三份。
分別為0-5500、5501-11000、11001-16384
當使用者發起了一個key的請求,叢集是如何處理請求的呢!
下圖的黑框代表這集群所有節點的槽信息,裡邊還有很多其它資訊。
如圖所示,使用者發起請求key,redis接收後計算key的槽位置,在根據槽位置找出對應的節點
如果存取的槽就在節點本身,那麼就會直接回傳key對應資料。
否則會回覆moved重定向錯誤, 並且給客戶端回傳正確的節點。
然後重發key指令
只需要注意喀喀爾圈中的設定資訊即可
咔噠給大家提供一個指令可以很方便的替換檔案sed 's/6379/6380/g' 6379-redis.conf > 6380-redis.conf
#按照這樣的方式建立出來6個不同連接埠的設定檔
隨便開啟一個設定檔查看,偵測是否取代成功為了查看日誌資訊方便,全部使用前台啟動。並且查看服務是否都正常啟動,執行指令ps -ef | grep redis
可以看到啟動後多了個cluster標識,代表著都是叢集的一個節點。 所有節點啟動完成,叢集啟動的指令需要基於ruby(喀喀使用redis版本為4.0)。接下來一起安裝
#執行指令wget https://cache.ruby-lang.org/pub /ruby/2.7/ruby-2.7.1.tar.gz
解壓縮:tar -xvzf ruby-2.7.1.tar.gz
根據自己下載的版本解壓縮
安裝:./configure | make | make install
這三個指令一氣呵成。
查看ruby和gem版本:ruby -v
#叢集的執行指令在/usr/local/redis/src/redis-trib.rb
注意如果需要直接使用redis-trib. rb
指令,需要ln到bin目錄下,否則就必須使用./redis-trib.rb
的方式。
如果按照步驟走,這裡會出現一個錯誤執行gem install redis
很不幸的是在這裡也會出現錯誤。 接著需要安裝yum install zlib-devel
和yum install openssl-devel
安裝完成後,在/ruby-2.7.1/ext/openssl
和/ruby-2.7.1/ext/zlib
分別執行#ruby extconf.rb
並且執行make | make install
然後在執行gem install redis
就OK這時在回頭來執行./redis -trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 1:638##1:638##.0.1:6383 1:632##1:632##1:632##1:632##1:632##1:632##1.解讀”
建立集群,並且給6個節點分配哈希槽,後三個節點配置為前三個節點的從節點顯示每個節點的哈希槽資訊和節點ID,最後一步需要輸入
來到data目錄下查看設定檔的變更。設定檔主要資訊是每個主節點分的槽「查看主機點的運行日誌」
這裡給的主要資訊cluster status changed:ok 叢集狀態正常
##當直接設定資料會報錯,並且把name這個key進行轉換後的槽位置為5798 並且給了ip位址和連接埠號碼。 需要使用指令redis-cli -c
在進行設定值的時候提示說重定向到5798的這個槽接下來進行取得數據,會自動的切換節點。
根據上文集群啟動資訊知道連接埠6383是6379的從節點。
接下來就是讓6383下線查看6379的日誌資訊。
6379會回報連接6383遺失,並且給上標記fail,表示不可用。這個時候集群還是正常工作的。
「總結:從節點下線對叢集沒有影響」當6383埠後,所有的節點會把fail的標記清除
# 手動下線主節點6379,查看從節點6383日誌資訊
#此時的6383節點會持續連接6379共10次。那為什麼是10次呢!
是根據我們配置的參數cluster-node-timeout 10
來決定的,這裡給我們一個資訊就是一秒鐘連接一次
直到時間到期後,開始故障轉移。
這時6383在故障轉移選舉中勝任,翻身奴隸把歌唱,成為了主節點。 此時在檢視一下叢集的節點訊息,指令cluster nodes
。
會發現這裡竟然存在四個主節點,但是其中一個主節點時下線狀態「6379原主節點上線」
6379上線後,同樣所有的節點也會清除fail資訊。
且節點資訊也會改變,此時的6379改變為6383的從節點。
#在新增兩個連接埠6385和6386執行新增指令./redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379
,這裡發送的就是meet訊息
#執行add-node指令,第一個參數為新節點的ip 連接埠 第二個參數為已存在叢集中的節點。根據下圖我們就可以看到新增的節點已經存在叢集中了。
「注意:雖然說6385已經成為集群中的節點了,但是跟其它節點有區別。它沒有數據,也就是沒有哈希槽」接下來我們就需要把叢集中的某些雜湊槽分配到這個新節點上,分配結束後這個節點才會成為真正意義上的主節點
執行指令./redis-trib.rb reshard 127.0.0.1:6385
會提示轉移多少個雜湊槽並填入接收節點的id
all#
使用指令:cluster nodes
查看,6385的這個節點就已經擁有三個範圍的雜湊槽了
「主節點已經新增好了,接下來就需要為6385這個主節點配置一個從節點6386”
指令:./redis-trib.rb add-node --slave --master-id dcc0ec4d0c932ac5c35ae76af4f9c5d27a42d0c932ac5c35ae76af4f9c5d27a422d9f 127.0.0.1:6386 127.0.0.1:6385
master-id是6385的id,第一個參數為新節點的ip 連接埠 第二個為指定的主節點ip 連接埠
#當想對叢集中的主節點進行升級的話可以手動執行故障轉移到從節點,避免叢集可用性受影響。
在從節點執行指令:cluster failover
#「執行過程」
檢視節點資訊就可以看到6386這個節點已經變成主機點了。
當給從節點發送cluster failover 指令後,從節點會傳送CLUSTERMSG_TYPE_MFSTART封包給主節點。從節點請求主節點停止訪問,從而對比兩者的資料偏移量達到一致。
這時客戶端不會連接我們淘汰的主節點,同時主節點向從節點發送複製偏移量,從節點得到複製偏移量後故障轉移開始,接著通知主節點進行配置切換,當客戶端在舊的master上解鎖後重新連接到新的主節點。
上文我們測試了故障轉移,主節點下線後從節點變成主節點,接下來剖析這個過程。
#叢集中的每個節點會定期的給其它節點發送ping訊息,接收方用pong作為回應。
如果在cluster-node-timeout的時間內ping訊息一直失敗,則會把接收方的節點標記為pfail狀態也就是主觀下線。
這個下線狀態是不是很熟悉。沒錯,這個跟哨兵判斷主節點是否異常有點相似。當一個哨兵發現主節點有問題時也會標記主節點客觀下線(s_down)。突然發現離題了,尷尬.......
在提一下哨兵,當一個哨兵認為主節點異常後標記主觀下線,但是其它哨兵怎麼能會同意,不能你說什麼就是什麼。都會去嘗試連接異常的主節點,當半數以上的哨兵都認為主節點異常後會直接讓其主節點客觀下線。
同樣叢集也不會因為一個節點判斷其狀態為下線就行的,節點直接透過Gossip訊息傳播,叢集中節點會不斷收集故障節點的下線回饋並且儲存到本地的故障節點下線報告中。當有半數以上的群集主節點都標記為主觀下線後改變狀態為客觀下線。
最後向叢集廣播一則fail訊息,通知所有節點將故障節點標記為客觀下線。
例如:節點A發送ping到節點B通訊異常後標記節點B為pfail,之後節點A會繼續給節點C發送ping並且攜帶節點B的pfail訊息然後節點C將節點B的故障保存到下線報告中。當下線報告數量大於有哈希槽主節點的一半數量以上後就會嘗試客觀下線。
當故障節點被定義為客觀下線後,故障節點的所有從節點承擔故障復原的責任。
故障復原是從節點透過定時任務發現自己的主機點客觀下線後就會執行故障復原流程。
「1. 資格檢查」
所有的從節點都會進行檢查與主節點最後的連線時間,斷線時間大於cluster-node-time*cluster -slave-validity-factor時不具備故障轉移的資格。
「2. 準備選舉時間」
先說為什麼這裡會有一個準備選舉時間。
資格檢查過後存在多個從節點,那麼就需要使用不同的延遲選舉時間來支援優先順序。這裡的優先順序就是 以複製偏移量為基準,偏移量越大與故障主節點的延遲越小,那麼就更有機會擁有替換主節點的機會。
主要的功能就是確保資料一致性最好的節點優先發起選舉
「3.選舉投票」
redis群集的投票機制沒有採用從節點進行領導選舉,這點切記不要跟哨兵搞混了。集群的投票機制都是持有槽的主機點進行投票的。
故障節點的從節點會廣播一個FAILOVER_AUTH_REQUEST 封包給所有的持有槽的主節點請求投票。
當主節點回覆FAILOVER_AUTH_ACK投票後在NODE_TIMEOUT * 2的這段時間不能給其它的從節點投票
從節點取得到半數以上的投票後就會進行故障復原階段
「4. 故障轉移」
選舉成功的從節點取消複製變為主節點
刪除故障節點的槽,並且將故障節點的槽委託到自己身上
#向叢集廣播自己的pong訊息,通知主機點的改變和接管了故障節點的槽資訊。
一篇利用兩個夜晚才弄完的redis哨兵文章,結果你們的關注點卻不在文章本身,啊!小編心很痛
為了滿足大家的要求,咔咔忍痛說如何設定亮瞎的背景。 咔咔使用的工具是xsheel開啟工具選擇選項接著到查看有個視窗透明就可以設定xsheel透明了。 對嘍!你想的沒錯這就是桌面背景,是不是準備開始設定去了。那設定完了回來再把文章看完好嗎?喀喀也需要各路大神給予技術點補充和辨別錯誤。
❝堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我們下期再見。
❞
#推薦:《redis教學》
以上是面試問Redis集群,被虐的不行了...的詳細內容。更多資訊請關注PHP中文網其他相關文章!