1. 程式人生 > >Redis總結(八)如何搭建高可用的Redis叢集

Redis總結(八)如何搭建高可用的Redis叢集

以前總結Redis 的一些基本的安裝和使用,大家可以這這裡檢視Redis 系列文章:https://www.cnblogs.com/zhangweizhong/category/771056.html。

今天補一下redis叢集功能吧。需要注意,Redis 3.0 以後才有叢集的功能,下載Redis的時候注意下版本。 

1. Redis叢集原理

先看看redis-cluster架構圖:

 

架構細節:

(1)所有的redis節點彼此互聯(PING-PONG機制),內部使用二進位制協議優化傳輸速度和頻寬。

(2)節點的fail是通過叢集中超過半數的節點檢測失效時才生效。

(3)客戶端與redis節點直連,不需要中間proxy層,客戶端不需要連線叢集所有節點,連線叢集中任何一個可用節點即可。

(4)redis-cluster把所有的物理節點對映到[0-16383]slot(雜湊槽)上,cluster 負責維護node<->slot<->value。

Redis 叢集中內建了 16384 個slot(雜湊槽),當需要在 Redis 叢集中放置一個 key-value 時,redis 先對 key 使用 crc16 演算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的雜湊槽,redis 會根據節點數量大致均等的將雜湊槽對映到不同的節點。

 

容錯機制: redis-cluster投票

 

 

(1)領著投票過程是叢集中所有master參與,如果半數以上master節點與master節點通訊超過(cluster-node-timeout),認為當前master節點掛掉.

(2):什麼時候整個叢集不可用(cluster_state:fail)? 

    a:如果叢集任意master掛掉,且當前master沒有slave.叢集進入fail狀態,也可以理解成叢集的slot對映[0-16383]不完成時進入fail狀態. 

    b:如果叢集超過半數以上master掛掉,無論是否有slave叢集進入fail狀態.

  注意:1. 當叢集不可用時,所有對叢集的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)錯誤。

     2. redis-3.0.0.rc1加入cluster-require-full-coverage引數,預設關閉,開啟改配置,允許叢集相容部分失敗。

 

2. 安裝Redis

redis 的單機安裝之前已經講過,網路上也有很多教程,這裡就不重複了。

文章最後提供了Redis 3.0 的原始碼,Redis叢集指令碼等資源。大家可以用我提供的版本來測試。

 

3. 安裝ruby環境

redis3.0 原始碼中自帶的叢集管理工具redis-trib.rb依賴ruby環境,首先需要安裝ruby環境:

1. 安裝ruby環境

yum install ruby

yum install rubygems   

 

2. 安裝ruby和redis的介面程式

拷貝redis-3.0.0.gem至/usr/local下

執行:gem install /usr/local/redis-3.0.0.gem

 

4. 建立叢集

叢集結點規劃

一般Redis叢集的例項,都安裝在各個主從伺服器上,這裡為了演示方便,只是在同一臺伺服器用不同的埠表示不同的redis伺服器,如下:

主節點:172.16.0.17:7001,172.16.0.17.3:7002,172.16.0.17:7003

從節點:172.16.0.17:7004,172.16.0.17:7005,172.16.0.17:7006

1. 在/usr/local下建立redis-cluster目錄,其下建立Redis01到Redis06等6個redis例項,埠號為:7001-7006,具體目錄如下:

 

 

2. 將redis原始碼目錄src下的redis-trib.rb拷貝到redis-cluster目錄下。

 

3. 修改每個redis例項的redis.conf配置檔案:

port 7001  //這裡要改成各個例項對應的埠,7001-7006
#bind 172.16.0.17
cluster-enabled yes

 

啟動每個結點redis服務

分別進入Redis01、Redis02、...Redis06目錄,執行:

./redis-server ./redis.conf

 

檢視redis程序:ps aux|grep redis

 

以上,Redis 的6個例項,就已經啟動了。

 

執行建立叢集命令

執行redis-trib.rb,此指令碼是ruby指令碼,它依賴ruby環境。

./redis-trib.rb create --replicas 1 172.16.0.17:7001 172.16.0.17:7002 172.16.0.17:7003 172.16.0.17:7004 172.16.0.17:7005  172.16.0.17:7006

說明:

redis叢集至少需要3個主節點,每個主節點有一個從節點總共6個節點

replicas指定為1表示每個主節點有一個從節點

 

注意:

如果執行時報如下錯誤:

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

解決方法是刪除生成的配置檔案nodes.conf,如果不行則說明現在建立的結點包括了舊叢集的結點資訊,需要刪除redis的持久化檔案後再重啟redis,比如:appendonly.aof、dump.rdb

 

建立叢集輸出如下:

>>> Creating cluster

Connecting to node 172.16.0.17:7001: OK

Connecting to node 172.16.0.17:7002: OK

Connecting to node 172.16.0.17:7003: OK

Connecting to node 172.16.0.17:7004: OK

Connecting to node 172.16.0.17:7005: OK

Connecting to node 172.16.0.17:7006: OK

>>> Performing hash slots allocation on 6 nodes...

Using 3 masters:

172.16.0.17:7001

172.16.0.17:7002

172.16.0.17:7003

Adding replica 172.16.0.17:7004 to 172.16.0.17:7001

Adding replica 172.16.0.17:7005 to 172.16.0.17:7002

Adding replica 172.16.0.17:7006 to 172.16.0.17:7003

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 172.16.0.17:7001

   slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 172.16.0.17:7002

   slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 172.16.0.17:7003

   slots:10923-16383 (5461 slots) master

S: 69d94b4963fd94f315fba2b9f12fae1278184fe8 172.16.0.17:7004

   replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

S: d2421a820cc23e17a01b597866fd0f750b698ac5 172.16.0.17:7005

   replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

S: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 172.16.0.17:7006

   replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

Can I set the above configuration? (type 'yes' to accept): yes

>>> Nodes configuration updated

>>> Assign a different config epoch to each node

>>> Sending CLUSTER MEET messages to join the cluster

Waiting for the cluster to join...

>>> Performing Cluster Check (using node 172.16.0.17:7001)

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 172.16.0.17:7001

   slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 172.16.0.17:7002

   slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 172.16.0.17:7003

   slots:10923-16383 (5461 slots) master

M: 69d94b4963fd94f315fba2b9f12fae1278184fe8 172.16.0.17:7004

   slots: (0 slots) master

   replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

M: d2421a820cc23e17a01b597866fd0f750b698ac5 172.16.0.17:7005

   slots: (0 slots) master

   replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

M: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 172.16.0.17:7006

   slots: (0 slots) master

   replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

 

5. 查詢叢集資訊

叢集建立成功登陸任意redis結點查詢叢集中的節點情況。

客戶端以叢集方式登陸:

./redis-cli -c -h 172.16.0.17 -p 7001 -c //其中-c表示以叢集方式連線redis,-h指定ip地址,-p指定埠號

 

查詢叢集資訊

cluster nodes 查詢叢集結點資訊

 

cluster info 查詢叢集狀態資訊

 

 

 

6. 新增主節點

叢集建立成功後可以向叢集中新增節點,下面是新增一個master主節點

1. 增加Redis07例項,參考叢集結點規劃章節新增一個“7007”目錄作為新節點。

 

2. 將Redis07例項新增到叢集中,執行下邊命令:

./redis-trib.rb add-node  172.16.0.17:7007 172.16.0.17:7001

 

3. 檢視叢集結點發現7007已新增到叢集中:

[root@VM_0_17_centos redis-cluster]# ./redis-trib.rb add-node  172.16.0.17:7007 172.16.0.17:7001
>>> Adding node 172.16.0.17:7007 to cluster 172.16.0.17:7001
Connecting to node 172.16.0.17:7001: OK
.
.
.
Connecting to node 172.16.0.17:7003: OK Connecting to node 172.16.0.17:7005: OK Connecting to node 172.16.0.17:7002: OK Connecting to node 172.16.0.17:7006: OK Connecting to node 172.16.0.17:7004: OK >>> Performing Cluster Check (using node 172.16.0.17:7001) M: 977962f18ec51f363747961137dc903f0078b248 172.16.0.17:7001 slots:0-5460 (5461 slots) master 1 additional replica(s) M: defe4ce0421ee6b50bdab3da58754e98cc80fca3 172.16.0.17:7003 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: a64fc273c0b90700397f5bac2b393dc5587d8ba8 172.16.0.17:7005 slots: (0 slots) slave replicates f277758189eba36c5b5732e9189d8554bf4385cb M: f277758189eba36c5b5732e9189d8554bf4385cb 172.16.0.17:7002 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 4f16e5adcc141ca284d4a9ec6d04f455aee84a48 172.16.0.17:7006 slots: (0 slots) slave replicates defe4ce0421ee6b50bdab3da58754e98cc80fca3 S: 479d5a077893184cd0b05a8e1b6cb5c0625215f4 172.16.0.17:7004 slots: (0 slots) slave replicates 977962f18ec51f363747961137dc903f0078b248 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. Connecting to node 172.16.0.17:7007: OK
.
.
. >>> Send CLUSTER MEET to node 172.16.0.17:7007 to make it join the cluster. [OK] New node added correctly.

 

雜湊槽重新分配

新增完主節點後,叢集並不會自動給新新增的節點分配雜湊槽,需要我們手動對主節點進行hash槽分配重新分配,這樣該主節才可以儲存資料。

redis叢集有16384個槽,叢集中的每個結點分配自已槽,通過檢視叢集結點可以看到槽佔用情況。可以看到剛才新增的主節點Redis07,沒有分配雜湊槽(slot)。

 

 

 下面就來說說如何給剛新增的Redis01結點分配槽:

第一步:連線上叢集

./redis-trib.rb reshard 172.16.0.17:7001   //(連線叢集中任意一個可用結點都行)

 

第二步:輸入要分配的槽數量

 

 

第三步:輸入接收槽的結點id

這裡準備給Redis07分配雜湊槽,通過cluster nodes檢視Redis07節點id為:e8461f9743e186ae8f67ed301d2d971186b1cc93

輸入:e8461f9743e186ae8f67ed301d2d971186b1cc93,

 

第四步:輸入源結點id

 

如果只是想從單個主節點獲取雜湊槽,那直接輸入相應的節點id即可。

如果想從所有的主節點獲取輸入:all,

 

第五步:輸入yes開始移動槽到目標結點id

 

 

第六步:分配完成之後,可以查詢叢集節點資訊,檢視雜湊槽是否分配成功。

 

 

 

7. 新增從節點

叢集建立成功後可以向叢集中新增節點,下面是新增一個slave從節點的命令。

./redis-trib.rb add-node --slave --master-id 主節點id 新增節點的ip和埠 叢集中已存在節點ip和埠

 

1. 新增Redis08例項為從結點,將Redis08作為Redis07的從結點。

執行如下命令:

./redis-trib.rb add-node --slave --master-id e8461f9743e186ae8f67ed301d2d971186b1cc93  172.16.0.17:7008 172.16.0.17:7001

e8461f9743e186ae8f67ed301d2d971186b1cc93  是Redis07例項的節點id,可通過cluster nodes檢視。

 

注意:如果原來該結點在叢集中的配置資訊已經生成叢集節點的配置檔案(如果叢集配置cluster-config-file預設指定則為nodes.conf),這時可能會報錯:

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

解決方法是:刪除生成的配置檔案nodes.conf,刪除後再執行./redis-trib.rb add-node指令

 

2. 檢視叢集中的結點,剛新增的Redis08已經成為Redis07的從節點:

 

 

8. 刪除結點:

叢集建立成功後可以向叢集中刪除其中的一個節點,應該怎麼刪除呢?

執行如下命令即可:

./redis-trib.rb del-node 172.16.0.17 :7005 e8461f9743e186ae8f67ed301d2d971186b1cc93

注意:刪除已經分配了有hash槽的節點會失敗,報錯如下:

[ERR] Node 172.16.0.17:7007 is not empty! Reshard data away and try again.

解決辦法就是:將該結點佔用的hash槽分配出去,請參考前面雜湊槽重新分配的操作,這裡就不重複了。

 

最後

以上就已經將如何搭建redis的叢集講完了。

redis3.0原始碼和ruby指令碼,點選這裡下載。

&n