1. 程式人生 > >超詳細,多圖文介紹redis叢集方式並搭建redis偽叢集

超詳細,多圖文介紹redis叢集方式並搭建redis偽叢集

# 超詳細,多圖文介紹redis叢集方式並搭建redis偽叢集 > 超多圖文,對新手友好度極好。敲命令的過程中,難免會敲錯,但為了截好一張合適的圖,一旦出現一點問題,為了好的演示效果,就要從頭開始敲。且看且珍惜。 再認識redis叢集前,若想先知道redis單機版的可檢視,[springboot整合redis](https://www.cnblogs.com/lgx211/p/11978701.html)。好了,下面開始了。 每個redis例項可稱為一個節點,安裝redis並以預設埠啟動是節點,不關閉,以另一個埠啟動,是一個新節點。在另一臺機器安裝redis並啟動,也是一個新節點。 節點分為主節點 (master) ,從節點 (slave) ,資料從主節點向多個從節點上同步 。 redis3.0開始支援叢集,redis叢集是沒有統一的入口的,客戶端(client)連線叢集的時候連線叢集中的任意節點(node)即可,叢集內部的節點是相互通訊的(PING-PONG機制)。 ### 一,叢集方式 ##### 1,主從模式 一個master可以擁有多個slave,但是一個slave只能對應一個master。這樣,當某個slave掛了不影響其他slave的讀和master的讀和寫,重新啟動後會,資料會從master上同步過來。 在主從模式下,因為只有一個主節點可以寫,而主,從節點都可以讀,所以通常主節點負責寫,從節點負責讀。 ![redis主從模式_lgx211](https://img-blog.csdnimg.cn/20200308100950473.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 但是,當唯一的master掛了以後,雖然這樣並不影響slave的讀,但redis也不再提供寫服務,需要將master重啟後,redis才重新對外提供寫服務。 ##### 2,Sentinel模式 sentinel模式是建立在主從模式的基礎上,避免單個master掛了以後,redis不能提供寫服務。因為從節點上備份了主節點的所有資料,那麼當master掛了以後,sentinel會在slave中選擇一個做為master,並修改它們的配置檔案,其他slave的配置檔案也會被修改,比如slaveof屬性會指向新的master,比如之前配置的密碼。此時,客戶端就不是直接連線Redis,而是連線sentinel的ip和port,由sentinel來提供具體Redis服務。 ![Sentinel模式_lgx211](https://img-blog.csdnimg.cn/20200308101043393.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 把之前掛了的master重新啟動後,它將不再是master而是做為slave接收新的master的同步資料。 ##### 3,Cluster模式 Cluster模式是建立在Sentinel模式的基礎上的,當資料多到需要動態擴容的時候,前面兩種就不行了,需要對資料進行分片,根據一定的規則把redis資料分配到多臺機器。 ![Cluster模式_lgx211](https://img-blog.csdnimg.cn/20200308101118670.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 該模式就支援動態擴容,可以線上增加或刪除節點,而且客戶端可以連線任何一個主節點進行讀寫,不過此時的從節點僅僅只是備份的作用。至於為何能做到動態擴容,主要是因為Redis 叢集沒有使用一致性hash, 而是使用的雜湊槽。Redis 叢集會有16384個雜湊槽,每個key通過CRC16校驗後對16384取模來決定放置哪個槽,而叢集的每個節點負責一部分hash槽。 那麼這樣就很容易新增或者刪除節點, 比如如果我想新添加個新節點, 我只需要從已有的節點中得部分槽到過來;如果我想移除某個節點,就只需要將該節點的槽移到其它節點上,然後將沒有任何槽的A節點從叢集中移除即可。由於從一個節點將雜湊槽移動到另一個節點並不會停止服務,所以無論新增刪除或者改變某個節點的雜湊槽的數量都不會造成叢集不可用的狀態。 需要注意的是,該模式下不支援同時處理多個key(如MSET/MGET),因為redis需要把key均勻分佈在各個節點上,併發量很高的情況下同時建立key-value會降低效能並導致不可預測的行為。 ### 二,搭建叢集 這裡就直接搭建較為複雜的Cluster模式叢集,也是企業級開發過程中使用最多的。 ##### 1,準備工作 Linux可以連線外網,有wget(用於線上下載redis),系統安裝好gcc環境,(不然編譯redis會報錯)。 ##### 2,下載、解壓、移到指定目錄,編譯Redis ```shell wget http://download.redis.io/releases/redis-5.0.4.tar.gz tar xzf redis-5.0.4.tar.gz mv redis-5.0.4 /usr/local/redis cd /usr/local/redis/redis-5.0.4 make make install ``` 安裝完成,在`/usr/local/bin/`目錄下就會看見 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101156131.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) ##### 3,建redis各節點目錄 ```shell mkdir /usr/local/redis-cluster cd /usr/local/redis-cluster mkdir -p 9001/data 9002/data 9003/data 9004/data 9005/data 9006/data mkdir bin ``` 最終目錄結構如下 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101224449.png) ##### 4,redis叢集的執行指令碼 把之前安裝好的redis的src目錄下執行指令碼拷貝過來,每個redis版本的執行指令碼有細微差異,請以你自己的版本為準,就是下圖綠色部分。 ```shell cd /usr/local/redis/redis-5.0.4/src cp mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server redis-trib.rb /usr/local/redis-cluster/bin ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101246212.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 最終效果如下圖所示 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101313119.png) ##### 5,批量複製redis例項 ```shell cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9001 cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9002 cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9003 cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9004 cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9005 cp /usr/local/redis/redis-5.0.4/* /usr/local/redis-cluster/9006 ``` 最終效果圖如下所示 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020030810133788.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) ##### 6,逐個修改redis配置 以 9001 的為例子,其餘五個類似。 ```shell cd /usr/local/redis-cluster/9001 vi redis.conf ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101400395.png) 開啟配置檔案,按 `i` 進入編輯模式,按照出現的順序,主要需要修改的地方是 - bind 192.168.119.128(綁定當前電腦的 IP,這是我虛擬機器的,你繫結成你虛擬機器的ip) - port 9001(因為我這是一臺機器執行6個redis例項,所以要啟動6個例項,得為它配置6個不同的埠,若你是6臺機器,預設的埠就行,無需更改) - daemonize yes(這是設定是否後臺啟動 Redis,預設 no ,但是生產環境肯定要預設就開啟 Redis,所以這裡設定為 yes 。) - pidfile /var/run/redis_9001.pid(_9001這個一定要和第一個配置的埠一樣) - dir /usr/local/redis-cluster/9001/data/(資料檔案存放位置,我換成指定目錄下存放) - appendonly yes - cluster-enabled yes(啟動叢集模式) - cluster-config-file nodes9001.conf(9001這個也要和之前的埠對應) - cluster-node-timeout 15000(超時時間) ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101439185.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 完成以上修改,Esc退出編輯模式,輸入`:wq` 儲存並退出。 類似同樣的操作操作再來五次。 若是對redis的配置檔案有興趣,我在學習的過程中找到個詳細的翻譯版,可點選連結進去學習。 [redis配置中文翻譯](https://github.com/linli8/cnblogs/blob/master/redis%E5%89%AF%E6%9C%AC.conf) ##### 7,逐個啟動redis節點 ```shell cd /usr/local/redis-cluster /usr/local/bin/redis-server /usr/local/redis-cluster/9001/redis.conf /usr/local/bin/redis-server /usr/local/redis-cluster/9002/redis.conf /usr/local/bin/redis-server /usr/local/redis-cluster/9003/redis.conf /usr/local/bin/redis-server /usr/local/redis-cluster/9004/redis.conf /usr/local/bin/redis-server /usr/local/redis-cluster/9005/redis.conf /usr/local/bin/redis-server /usr/local/redis-cluster/9006/redis.conf ``` 執行效果如圖所示 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101511379.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 現在檢查一下是否成功開啟,如下圖所示,都開啟成功。 ```shell ps -el | grep redis ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101536238.png) ##### 8,搭建叢集 此時的節點雖然都啟動成功了,但他們還不在一個叢集裡面,不能互相發現,測試會報錯:`(error) CLUSTERDOWN Hash slot not served`。 ```shell /usr/local/redis-cluster/bin/redis-cli -h 192.168.119.128 -p 9001 keys * set name mafly ``` 如下圖所示 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101602203.png) 解決報錯,如果你是redis5.0以前的,你需要安裝叢集所需的ruby相關依賴 ```shell yum install ruby yum install rubygems cd /usr/local/redis-cluster/ gem install redis ``` 這步若安裝報錯,請檢視[Could not find a valid gem 'redis'](https://www.cnblogs.com/lgx211/p/12425423.html)。 如果你是redis5.0及之後的,無需安裝ruby依賴,redis安裝目錄裡內建了叢集命令列工具 redis-trib ,它是一個 Ruby 程式, 這個程式通過向例項傳送特殊命令來完成建立新叢集, 檢查叢集, 或者對叢集進行重新分片工作。 ```shell redis-cli --cluster create 192.168.119.128:9001 192.168.119.128:9002 192.168.119.128:9003 192.168.119.128:9004 192.168.119.128:9005 192.168.119.128:9006 --cluster-replicas 1 ``` --cluster-replicas 1 這個指的是從機的數量,表示我們希望為叢集中的每個主節點建立一個從節點。 紅色選框是給三個主節點分配的共16384個槽點。 黃色選框是主從節點的分配情況。 藍色選框是各個節點的詳情。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101636474.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) ##### 9,測試 現在通過客戶端命令連線上,通過叢集命令看一下狀態和節點資訊等 ```shell /usr/local/redis-cluster/bin/redis-cli -c -h 192.168.119.128 -p 9001 cluster info cluster nodes ``` 效果圖如下,叢集搭建成功。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101657956.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 現在往9001這個主節點寫入一條資訊,我們可以在9002這個主節點取到資訊,叢集間各個節點可以通訊。 現在往9001這個主節點寫入一條資訊,我們可以在9002這個主節點取到資訊,叢集間各個節點可以通訊。 ```shell set name lgx get name ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101715657.png) ### 三,故障轉移 ##### 1,故障轉移機制詳解 1. 叢集中的節點會向其它節點發送PING訊息(該PING訊息會帶著當前叢集和節點的資訊),如果在規定時間內,沒有收到對應的PONG訊息,就把此節點標記為疑似下線。 2. 當被分配了slot槽位的主節點中有超過一半的節點都認為此節點疑似下線(就是其它節點以更高的頻次,更頻繁的與該節點PING-PONG),那麼該節點就真的下線。 3. 其它節點收到某節點已經下線的廣播後,把自己內部的叢集維護資訊也修改為該節點已事實下線。 4. 節點資格審查:然後對從節點進行資格審查,每個從節點檢查最後與主節點的斷線時間,如果該值超過配置檔案的設定,那麼取消該從節點的資格。 5. 準備選舉時間:這裡使用了延遲觸發機制,主要是給那些延遲低的更高的優先順序,延遲低的讓它提前參與被選舉,延遲高的讓它靠後參與被選舉。(延遲的高低是依據之前與主節點的最後斷線時間確定的) 6. 選舉投票:當從節點獲取選舉資格後,會向其他帶有slot槽位的主節點發起選舉請求,由它們進行投票,優先順序越高的從節點就越有可能成為主節點,當從節點獲取的票數到達一定數值時(如叢集內有N個主節點,那麼只要有一個從節點獲得了N/2+1的選票即認為勝出),就會替換成為主節點。 7. 替換主節點:被選舉出來的從節點會執行slaveof no one把自己的狀態從slave變成master,然後執行clusterDelSlot操作撤銷故障主節點負責的槽,並執行 clusterAddSlot把這些槽分配給自己,之後向叢集廣播自己的pong訊息,通知叢集內所有的節點,當前從節點已變為主節點。 8. 接管相關操作:新的主節點接管了之前故障的主節點的槽資訊,接收和處理與自己槽位相關的命令請求。 ##### 2,故障轉移測試 這是之前叢集中具體節點的情況,我簡化成如下,可以向上回看圖片中的叢集資訊。 ![原先叢集_lgx211](https://img-blog.csdnimg.cn/20200308101749519.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 這裡關閉該9001埠的程序,即模擬該主節點掛掉。 ```shell netstat -tunlp | grep 9001 kill 15705 ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020030810180938.png) 登入掛掉的redis節點,會被拒絕服務,通過還在正常執行的某個主節點進入,然後再次檢視叢集中的資訊 ```shell /usr/local/redis-cluster/bin/redis-cli -c -h 192.168.119.128 -p 9001 /usr/local/redis-cluster/bin/redis-cli -c -h 192.168.119.128 -p 9002 cluster nodes ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101822812.png) 簡而言之,就是之前的叢集資訊變成了如下所示 ![故障轉移後集群_lgx211](https://img-blog.csdnimg.cn/20200308101836175.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFFFF,t_70) 現在,我重啟剛才掛掉的主節點,重新檢視叢集內部的節點情況,具體情況如下圖所示。 ```shell cd /usr/local/redis-cluster/ /usr/local/bin/redis-server /usr/local/redis-cluster/9001/redis.conf /usr/local/redis-cluster/bin/redis-cli -c -h 192.168.119.128 -p 9002 cluster nodes ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200308101858676.png) 簡而言之,現在叢集內的節點情況如下 ![恢復後集群_lgx211](https://img-blog.csdnimg.cn/20200308101925841.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1MDIxMg==,size_16,color_FFFF