1. 程式人生 > >Redis Cluster 叢集的實現和管理

Redis Cluster 叢集的實現和管理

系統環境

CentOS 7

叢集規劃

在一臺物理機(實際部署應當分散到多個物理機上),建立6個redis節點,其中3個主節點、3個從節點。
節點表:
IP 埠 主從 路徑
192.168.1.21 7001 主 ~/redis-cluster/7001/
192.168.1.21 7002 主 ~/redis-cluster/7002/
192.168.1.21 7003 主 ~/redis-cluster/7003/
192.168.1.21 7011 從 ~/redis-cluster/7011/
192.168.1.21 7012 從 ~/redis-cluster/7012/
192.168.1.21 7013 從 ~/redis-cluster/7013/

建立步驟

01. 準備環境

# yum install gcc
# yum install ruby
# yum install ruby-devel.x86_64
# yum install rubygems
# gem sources -r https://rubygems.org
# gem sources -a http://rubygems.org  
# gem install redis

02. 下載安裝 redis

# cd~
# wget http://download.redis.io/releases/redis-3.0.7.tar.gz
# tar zxfv redis-3.0.7.tar.gz
# cd redis-3.0.7 # make MALLOC=libc # cp src/redis-server /usr/local/bin # cp src/redis-cli /usr/local/bin # cp src/redis-trib.rb /usr/local/bin

03. 獨立啟動/停止 redis

# redis-server &
# redis-cli shutdown

04. 測試獨立 redis

# redis-cli -p 7001
127.0.0.1:7001> set mykey myval01
127.0.0.1:7001> get mykey
"myval01"

05. 建立叢集環境

# cd~
# mkdir redis-cluster
# cd redis-cluster
# mkdir 7001 7002 7003 7011 7012 7013

建立配置檔案 ~/redis-cluster/redis.conf,內容如下:

port 7001
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

檔案中的 cluster-enabled 選項用於開例項的叢集模式, 而 cluster-conf-file 選項則設定了儲存節點配置檔案的路徑, 預設值為 nodes.conf。該節點配置檔案無須人為修改,它由Redis叢集在啟動時自動建立, 並在有需要時自動進行更新。
若要讓叢集正常運作至少需要三個主節點,我們的環境中,每個主節點附帶一個從節點,所以一共六個節點。

為每個節點建立配置檔案

# cd ~/redis-cluster
# cp redis.conf ./7001/
# …
# cp redis.conf ./7013/

修改各個目錄下的 redis.conf 檔案中的 port 為各自對應的埠

06. 啟動各個節點

# cd ~/redis-cluster
# cd 7001
# redis-server redis.conf
# cd ../7002
# redis-server redis.conf
# …
# cd ../7013
# redis-server redis.conf

檢視redis的啟動情況

# ps -ef | grep redis

07. 建立叢集

現在我們已經有了六個正在執行中的 Redis 例項, 接下來我們需要使用這些例項來建立叢集。
通過使用 Redis 叢集命令列工具 redis-trib , 編寫節點配置檔案的工作可以非常容易地完成: redis-trib 位於 Redis 原始碼的 src 資料夾中, 它是一個 Ruby 程式, 這個程式通過向例項傳送特殊命令來完成建立新叢集, 檢查叢集, 或者對叢集進行重新分片(reshared)等工作。這裡通過create命令來建立叢集。

# cd ~/redis-3.0.0/src
# ./redis-trib.rb create --replicas 1 192.168.1.21:7001 192.168.1.21:7002 192.168.1.21:7003 192.168.1.21:7011 192.168.1.21:7012 192.168.1.21:7013

說明:
這裡的IP地址必須是真實的IP,不能使用迴環 127.0.0.1 地址。

–replicas 1 即每一個master有1個slave;順序為 m m m s s s
redis-trib 會打印出一份預想中的配置給你看, 如果你覺得沒問題的話, 就可以輸入 yes , redis-trib 就會將這份配置應用到叢集當中,讓各個節點開始互相通訊。

輸入yes,然後配置完成。

以上資訊的其中一部分可以通過向叢集中的任意節點(主節點或者從節點都可以)傳送 CLUSTER NODES 命令來獲得。該命令還可以獲得節點 ID , IP 地址和埠號, 標誌(flag), 最後傳送 PING 的時間, 最後接收 PONG 的時間, 連線狀態, 節點負責處理的槽。

# redis-cli -p 7001 cluster nodes

08. 叢集檢查

./redis-trib.rb check 127.0.0.1:7001

09. 連線Redis叢集

通過上面的輸出,我們可以看出Redis三個主節點的slot範圍。一個 Redis 客戶端可以向叢集中的任意節點(包括從節點)傳送命令請求。我們首先連線第一個節點:

# redis-cli -p 7001

127.0.0.1:7001> set a 1 
(error) MOVED 15495 127.0.0.1:7003
127.0.0.1:7001> get a
(error) MOVED 15495 127.0.0.1:7003
127.0.0.1:7001> set b 1
OK

雖然我們用Node ID來標識叢集中的節點, 但是為了讓客戶端的轉向操作儘可能地簡單, 節點在 MOVED 錯誤中直接返回目標節點的 IP 和埠號, 而不是目標節點的 ID 。客戶端應該記錄槽15495由節點127.0.0.1:7003負責處理“這一資訊, 這樣當再次有命令需要對槽15495執行時, 客戶端就可以加快尋找正確節點的速度。這樣,當叢集處於穩定狀態時,所有客戶端最終都會儲存有一個雜湊槽至節點的對映記錄,使得叢集非常高效: 客戶端可以直接向正確的節點發送命令請求, 無須轉向、代理或者其他任何可能發生單點故障(single point failure)的實體(entiy)。

10. 新增新master節點

a. 啟動節點

# cd ~/redis-cluster
# mkdir 8001
# cp ./redis.conf ./8001
# cd 8001
# redis-server redis.conf

b. 將節點加入到叢集

# redis-trib.rb add-node 127.0.0.1:8001 127.0.0.1:7001

說明:
第一個 ip:port 為新節點
第二個 ip:port 是任意一個已經存在的節點
新節點沒有包含任何資料,也沒有包含任何slot。
當叢集需要將某個從節點升級為新的主節點時, 這個新節點不會被選中,同時新的主節點因為沒有包含任何slot,不參加選舉和failover。

c. 為新節點分配 slot

# redis-trib.rb reshard 127.0.0.1:8001  
#根據提示選擇要遷移的slot數量(ps:這裡選擇500)  
How many slots do you want to move (from 1 to 16384)? 500  
#選擇要接受這些slot的node-id  
What is the receiving node ID? f51e26b5d5ff74f85341f06f28f125b7254e61bf  
#選擇slot來源:  
#all表示從所有的master重新分配,  
#或者資料要提取slot的master節點id,最後用done結束  
Please enter all the source node IDs.  
  Type 'all' to use all the nodes as source nodes for the hash slots.  
  Type 'done' once you entered all the source nodes IDs.  
Source node #1:all  
#列印被移動的slot後,輸入yes開始移動slot以及對應的資料.  
#Do you want to proceed with the proposed reshard plan (yes/no)? yes  
#結束  

11. 新增新的 Slave 節點

a. 啟動節點

# cd ~/redis-cluster
# mkdir 8011
# cp ./redis.conf ./8011
# cd 8011
# redis-server redis.conf

b. 將節點加入到叢集
方法一:

# redis-trib.rb add-node -slave 127.0.0.1:8011 127.0.0.1:7001

說明:
第一個 ip:port 為新節點
第二個 ip:port 是任意一個已經存在的節點
新的節點會作為叢集中其中一個主節點的從節點,一般來說是從節點最少的主節點。

方法二:

# redis-trib.rb add-node -slave -master-id \ 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:8011 127.0.0.1:7001

說明:
-master-id xxxx 主節點的 ID
第一個 ip:port 為新節點
第二個 ip:port 是任意一個已經存在的節點

注意:線上新增slave 時,需要bgsave整個master資料,並傳遞到slave,再由 slave載入rdb檔案到記憶體,rdb生成和傳輸的過程中消耗Master大量記憶體和網路IO,以此不建議單例項記憶體過大,線上小心操作。

12. 線上 reshard 資料

對於負載/資料不均勻的情況,可以線上reshard slot來解決,方法與新增新master的reshard一樣,只是需要reshard的master節點是已存在的老節點。

# redis-trib.rb reshard 127.0.0.1:7003

13. 刪除一個 slave 節點

# redis-trib.rb del-node ip:port '<node-id>'  
# redis-trib.rb del-node 127.0.0.1:7001 'c7ee2fca17cb79fe3c9822ced1d4f6c5e169e378' 

說明:
ip:port 叢集中已有的任意一節點(不是被刪除的節點)
被刪除節點的 ID

14. 刪除一個 master 節點(7003)

刪除master節點之前首先要使用reshard移除master的全部slot,然後再刪除當前節點。 (目前redis-trib.rb只能把被刪除master的slot對應的資料遷移到一個節點上)。

a. 遷移 slot

#把127.0.0.1:7003當前master遷移到127.0.0.1:7002上  
redis-trib.rb reshard 172.0.0.1:7002  
#根據提示選擇要遷移的slot數量(ps:這裡選擇500)  
How many slots do you want to move (from 1 to 16384)? 500(被刪除master的所有slot數量)  
#選擇要接受這些slot的node-id(172.0.0.1:7002)  
What is the receiving node ID? c4a31c852f81686f6ed8bcd6d1b13accdc947fd2 (ps:172.0.0.1:7002的node-id)  
Please enter all the source node IDs.  
  Type 'all' to use all the nodes as source nodes for the hash slots.  
  Type 'done' once you entered all the source nodes IDs.  
Source node #1:f51e26b5d5ff74f85341f06f28f125b7254e61bf(被刪除master的node-id)  
Source node #2:done  
#列印被移動的slot後,輸入yes開始移動slot以及對應的資料.  
#Do you want to proceed with the proposed reshard plan (yes/no)? yes  

b. 刪除空的 master 節點

# redis-trib.rb del-node 172.0.0.1:7001 'f51e26b5d5ff74f85341f06f28f125b7254e61bf'  

說明:
ip:port 叢集中已有的任意一節點(不是被刪除的節點)
被刪除節點的 ID

15. 改變從節點的隸屬關係(從節點 7013)

# redis-cli -p 7013
127.0.0.1:7013> cluster replicate 2b9ebcbd627ff0fd7a7bbcc5332fb09e72788835
說明:
  2b9ebcbd627ff0fd7a7bbcc5332fb09e72788835  為新的主節點的 ID

16. 叢集的關閉和重啟

redis cluster官方文件,沒發現有關叢集重啟和關閉的方法。主要是因為在正式的環境中叢集一般都由3臺物理機構成,3臺物理機同時掛掉的可能性極小。只要不同時掛掉,掛掉的機器修復後在加入叢集,叢集都能良好的運作,萬一同時掛掉,資料又沒有備份的話,就有大麻煩了。

redis cluster叢集中的節點基本上都對等的,沒有管理節點。如果要讓所有節點都關閉,只能關閉所有 redis-server 程序。

# pkill -9 redis

然後重新啟動,如果直接重啟會報告錯誤。

# redis-trib.rb create --replicas 1 xxx xxx xxx xxx

會報以下錯誤,

[ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

第一次啟動叢集時,~/redis-cluster/7001/ 下只有 redis.conf,而現在重啟時,此目錄下有了別的檔案,所有報錯。簡單的方法是將除了 redis.conf 外的其他檔案全部刪除,在啟動肯定是可以的,但是叢集是有資料的,所以需要保留了配置檔案 redis.conf 和資料檔案 *.rdb。
這樣是可以啟動的,但是原來的資料還是丟失了,不知道是自己的想法不對。

需要注意的問題

  1. 執行06步驟時,節點目錄下(7001/7002/…/7013/ 應當只有 redis.conf 檔案)

  2. 一定要嚴格執行 01 步驟準備好環境。
    此步驟中 gem sources 預設地址好像無法訪問,建議用下面方法替換

# gem sources -r https://rubygems.org
# gem sources -a http://rubygems.org