Redis集羣之Redis-Cluster實踐詳解

Redis Cluster 官網地址:https://redis.io/topics/cluster-tutorial 。 本篇博文背景使用Redis 5.X,低版本的可能不太適用,具體參考官網。

【1】基礎入門

Redis Cluster集羣保證高可用但是不支持強一致性,具有自動切分數據集到多個節點上的能力,當部分節點宕機或無法通訊的情況下仍可繼續處理命令。但是如果大部分節點掛掉,那麼該集羣就停止工作。

① Redis Cluster需要的TCP端口

每一個redis集羣的節點需要開通兩個TCP端口。一個是用於客戶端的Redis TCP,如6379。另一個由客戶端加10000所得,如16379,用於Redis集羣總線連接。 這是一個用戶 節點對節點的 二進制協議通訊通道。集羣總線是用來處理節點的失效檢測,配置更新,災備授權等事情。

集羣總線使用了一種不同的二進制協議,供節點和節點之間交換信息用。該協議可以讓節點和節點之間以更小的流量和和更短的時間來交換信息。

② 數據是怎麼在cluster中存放的

Redis集羣用的不是基於哈希值的分片方式,用的是另一種不同的分片方式-hash slot。在該分片方式下所有鍵在概念上都是我們稱之爲哈希槽的一部分。

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

Redis集羣中的每個節點都存放了一些哈希槽。所以舉例來說,比如你有3個節點:

節點A 保存了從 0 到 5500 的哈希槽
節點B 保存了從 5501 到 11000的哈希槽
節點C 保存了從 11001 到 16384 的哈希槽

這麼做讓集羣增加或者減少節點變得很簡單。比如我要增加一個節點D,我只需要從節點ABC移動一部分哈希槽到D。如果我要從節點中去除節點A,我只需要把節點A上的哈希槽移動到節點B或者C。當節點A的哈希槽被全部移走了之後,我就可以將它從節點中完全去除。

因爲把哈希槽從一個節點移動到另外一個節點並不需要停止集羣, 所以增加、刪除節點或者在各節點間調整哈希槽的佔有率的時候是不用停止集羣的。Redis集羣支持在一條命令裏面對同一個哈希槽的多個鍵同時操作(或者在一個事務中,或者在一個lua腳本執行過程中)。

用戶可以通過哈希標籤強制的把多個鍵放到一個哈希槽裏面。在Redis集羣手冊中可以查到哈希標籤的相關說明, 不過歸納成一句話就是:當有在key裏面寫上段包含在{...}中的文字的時候,之後大括號{...}中的文字會被計算成哈希鍵。比如有兩個key一個名叫 this{foo}key 另一個名叫 another{foo}key ,這兩個key會被歸納到同一個哈希槽裏面。這樣這兩個key就可以在一個命令中同時進行操作了。


③ Redis 集羣主從模型

爲了在部分節點失敗或者無法通信的情況下集羣仍然可用,Redis 集羣採用了一種 主從模型。在該模型下每一個哈希槽都會被從master端複製N份到slave節點。在上面例子中有三個節點分別是ABC,如果節點B掛掉了,集羣就無法繼續工作,因爲從5501到11000的哈希槽就沒了。

不過如果當集羣被創建的時候(遲些時候也可以)我們給每一個master節點增加一個slave從節點。模型變成這樣:集羣中有三個節點A,B,C,以及他們各自的從節點 A1,B1,C1,當節點B掛掉的時候,系統還可以正常運行。節點B1是用來做爲節點B的鏡像的。當節點B掛掉了,集羣會選舉B1作爲新的master節點,並繼續運行下去。不過要注意當節點B和節點B1都掛掉的時候,redis集羣還是無法繼續運行。


④ Redis 集羣一致性保證

Redis 集羣並不能保證數據的強一致性。在實際應用中這意味着在特定的情況下,就算Redis 集羣告知客戶端已經收到了寫請求,這個寫請求仍然有可能丟失。Redis集羣之所以會丟失寫請求的首要原因是:它採用了異步的複製機制

在write的時候會經歷以下的步驟:

你的客戶端發送了一個寫請求給master B 節點
master B 節點回復了一個OK給你的客戶端。
master B 節點把這個寫請求傳播到它的 slave B1, B2, B3 節點上去。

正如你所見, B節點並不會等到B1,B2,B3節點都回復它之後纔回復OK給客戶端。因爲這樣會造成redis集羣過高的延遲度。所以如果你的客戶端正在寫入,節點B告知你的客戶端它收到了寫請求,但是在它把這個寫請求發送給它的slave節點們之前,節點B掛了,那麼其中一個slave節點(假設它還沒收到寫請求)被選舉爲master那麼你這個寫請求就永久的丟失了。

Redis集羣也支持同步寫入(但是就會導致性能降低,需要在高性能和強一致性做權衡)。它通過實現WAIT命令來實現。這樣一來基本不會丟失寫操作。但是請注意就算你使用了同步複製,Redis集羣也不能達到強一致性,因爲總是會遇到某些更復雜的錯誤場景,比如一個slave節點在被選舉爲master的時候不能收到寫請求命令。

還有一個需要注意的會丟失數據的情況。當進行一次網絡網絡分裂的時候某個客戶端被分配到一個擁有很少節點的區域中的情況。

就拿我們的6節點例子(master是ABC,slave是A1,B1,C1),此時有一個客戶端,我們稱之爲Z1。當網絡分裂後,有可能有這種情況:現在有2方,一方是 A,C,A1,B1,C1,另一方是B和Z1。Z1依然可以寫入B,而且B也會接受來自Z1的寫請求。如果這次網絡分裂在很短的時間內被修復, 集羣依然會保持正常運行。 然而如果網絡分裂持續了較長時間,長到足夠B1在多數方被選舉爲master。那麼Z1發送給B的寫請求都會丟失。

注意, 在網絡分裂出現期間, 客戶端 Z1 可以向主節點 B 發送寫命令的最大時間是有限制的, 這一時間限制稱爲節點超時時間(node timeout), 是 Redis 集羣的一個重要的配置選項。

  • 對於majority 一方來說, 如果一個主節點未能在節點超時時間所設定的時限內重新加入集羣, 那麼集羣會將這個主節點視爲下線, 並使用從節點替換掉。
  • 對於minority 一方, 如果一個主節點未能在節點超時時間所設定的時限內重新聯繫上集羣, 那麼它將停止處理寫命令, 並向客戶端報告錯誤。

⑤ 集羣配置一些參數

集羣配置參數主要有:

cluster-enabled <yes/no>
cluster-config-file <filename>
cluster-node-timeout <milliseconds>
cluster-slave-validity-factor <factor>
cluster-migration-barrier <count>
cluster-require-full-coverage <yes/no>

詳細解釋如下:

  • cluster-enabled <yes/no>: 該項如果設置成yes,該實例支持redis集羣。否則該實例會像往常一樣以獨立模式啓動。
  • cluster-config-file <filename>: 必須注意到儘管該項是可選的,這並不是一個用戶可以編輯的配置文件,這是redis集羣節點自動生成的配置文件,每次一旦配置有修改它都通過該配置文件來持久化配置(基本上都是狀態),這樣在下次啓動的時候可以重新讀取這些配置。該文件中列出了該集羣中的其他節點的狀態,持久化變量等信息。 當節點收到一些信息的時候該文件就會被衝重寫。
  • cluster-node-timeout <milliseconds>: redis集羣節點的最大超時時間。響應超過這個時間的話該節點會被認爲是掛掉了。如果一個master節點超過一定的時候無法訪問,它會被它的slave取代。 該參數在redis集羣配置中很重要。很明顯,當節點無法訪問大部分master節點超過一定時間後,它會停止接受查詢請求。
  • cluster-slave-validity-factor <factor>:如果將該項設置爲0,不管slave節點和master節點間失聯多久都會一直嘗試failover(設爲正數,失聯大於一定時間(factor*節點TimeOut),不再進行FailOver)。比如,如果節點的timeout設置爲5秒,該項設置爲10,如果master跟slave之間失聯超過50秒,slave不會去failover它的master(意思是不會去把master設置爲掛起狀態,並取代它)。注意:任意非0數值都有可能導致當master掛掉又沒有slave去failover它,這樣redis集羣不可用。在這種情況下只有原來那個master重新回到集羣中才能讓集羣恢復工作。
  • cluster-migration-barrier <count>: 一個master可以擁有的最小slave數量。該項的作用是,當一個master沒有任何slave的時候,某些有富餘slave的master節點,可以自動的分一個slave給它。具體參見手冊中的replica migration章節
  • cluster-require-full-coverage <yes/no>: 如果該項設置爲yes(默認就是yes) 當一定比例的鍵空間沒有被覆蓋到(就是某一部分的哈希槽沒了,有可能是暫時掛了)集羣就停止處理任何查詢炒作。如果該項設置爲no,那麼就算請求中只有一部分的鍵可以被查到,一樣可以查詢(但是有可能會查不全)

【2】Redis Cluster部署

① 下載安裝redis-5.0.4.tar.gz

不會安裝的可以參考博文:CentOS7 下源碼安裝Redis並配置服務開機啓動 ,注意這裏只編譯安裝就可以,不需要做成服務開機啓動。

② 創建文件夾存放配置和日誌以及pid等

目錄如下所示,conf中存放不同redis實例的配置文件,logs存放不同redis實例的日誌文件,pids存放不同實例的pid文件。redisinstall是第一步中redis的安裝目錄(/opt/redis-cluster/redisinstall)。
在這裏插入圖片描述

③ 編輯redis實例配置文件

Redis官網給了最小配置實例:

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

這裏進行修改,主要配置如下(可根據需要自行修改配置):

#bind 127.0.0.1
port 7000
daemonize yes
pidfile /opt/redis-cluster/pids/redis-7000.pid
logfile "/opt/redis-cluster/logs/redis-7000.log"
dbfilename dump-7000.rdb
appendonly yes
appendfilename "appendonly-7000.aof"
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 15000

如下所示,可啓動每個實例:

[root@localhost bin]# ./redis-server ../../conf/redis-7000.conf
[root@localhost bin]# ps -ef|grep redis
root      17809      1  0 22:11 ?        00:00:00 ./redis-server *:7000 [cluster]          
root      17816  13225  0 22:11 pts/0    00:00:00 tail -f redis-7000.log
root      17852  11902  0 22:12 pts/1    00:00:00 grep redis
[root@localhost bin]# ./redis-server ../../conf/redis-7001.conf
[root@localhost bin]# ./redis-server ../../conf/redis-8000.conf
[root@localhost bin]# ./redis-server ../../conf/redis-8001.conf
[root@localhost bin]# ./redis-server ../../conf/redis-9000.conf
[root@localhost bin]# ./redis-server ../../conf/redis-9001.conf

再次查看redis的安裝目錄(/opt/redis-cluster/redisinstall/bin)bin目錄如下:
在這裏插入圖片描述
其中nodes-*.conf保存了對應實例的節點信息,內容如下所示(目前都是主):

//7000 實例
[root@localhost conf]# tail -f ../redisinstall/bin/nodes-7000.conf
2a470dfa7453c058ae5d92d67e8164026f4a3652 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

//7001 實例
[root@localhost conf]# more ../redisinstall/bin/nodes-7001.conf
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

//8000 實例
[root@localhost conf]# more ../redisinstall/bin/nodes-8000.conf
62b736242d1ed6f619ae13fbf90da5a737a44449 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

//8001實例
[root@localhost conf]# more ../redisinstall/bin/nodes-8001.conf
c57cb1e504c386e7337eef47dd83278da802ea6f :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

//9000 實例
[root@localhost conf]# more ../redisinstall/bin/nodes-9000.conf
49913b6e8c220010d9f02c6b4df56f13cf7524e8 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

// 9001 實例
[root@localhost conf]# more ../redisinstall/bin/nodes-9001.conf
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

創建集羣

./redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:8000 127.0.0.1:8001 127.0.0.1:9000 127.0.0.1:9001 --cluster-replicas 1

注意,這種方式創建的集羣會自動選擇從節點隨機分配到一個主節點上。如果需要指定主從關係,下面再實踐。如下是創建集羣后的結果:
在這裏插入圖片描述
輸入yes,表示接受:
在這裏插入圖片描述
至此,集羣就創建完成,從7000的日誌可以看到8001作爲其從節點。
在這裏插入圖片描述


【3】Redis Cluster 操作

① 查看集羣信息

bin目錄下執行如下命令:

./redis-cli -p 7000 cluster nodes

結果如下:

[root@localhost bin]# ./redis-cli -c -p 7000
127.0.0.1:7000> cluster nodes
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574070202801 8 connected 5461-10922
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574070201791 7 connected 0-5460
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574070202000 6 connected
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 myself,slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574070199000 1 connected
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574070201000 8 connected
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574070200000 3 connected 10923-16383

關於上面信息解釋:

1. id: 節點ID,一個40字節的隨機字符串,節點創建時生成,且不會變化(除非使用CLUSTER RESET HARD命令)。

2. ip:port: 客戶端訪問的地址。

3. flags: 逗號分隔的標記位,可能值有:myself, master, slave, fail?, fail, handshake, noaddr, noflags。

4. master -: 若是已知master節點的slave,這裏出現的是master的節點ID,否則是"-"。或者是slave 對應的master_id

6. ping-sent: 最近一次發送ping的unix毫秒時間戳,0代表沒有發送過。

7. pong-recv: 最近一次收到pong的unix毫秒時間戳。

8. config-epoch: 該節點或其master節點的epoch值。每次故障轉移都會生成一個新的,唯一的,遞增的epoch值。若多個節點競爭相同的slot,epoch值大的獲勝。

9. link-state: 節點和集羣總線間的連接狀態,可以是connected或disconnected。

10. slot: 該節點負責的slot,只有master會有這個提示

其中flags字段各標記含義如下:

myself: 當前連接的節點。

master: 節點是master。

slave: 節點是slave。

fail?: 節點處於pfail狀態,當前節點無法和其聯繫,但其它節點可以。

fail: 節點處於fail狀態,大多數節點都無法和其聯繫,將其由pfail升級到fail狀態。

handshake: 還沒完全加入集羣,正在握手階段。

noaddr: 不知道節點地址。

noflags: 沒有任何標記。

② 使用redis-cli操作cluster

查看 幫助命令redis-cli --cluster help,使用方式redis-cli --cluster 操作 操作選項,如redis-cli --cluster info 127.0.0.1:7000

redis-cli --cluster help
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN   #創建集羣
                 --cluster-replicas <arg>      #從節點個數
  check          host:port                     #檢查集羣
                 --cluster-search-multiple-owners #檢查是否有槽同時被分配給了多個節點
  info           host:port                     #查看集羣狀態
  fix            host:port                     #修復集羣
                 --cluster-search-multiple-owners #修復槽的重複分配問題
  reshard        host:port                     #指定集羣的任意一節點進行遷移slot,重新分slots
                 --cluster-from <arg>          #需要從哪些源節點上遷移slot,可從多個源節點完成遷移,以逗號隔開,傳遞的是節點的node id,還可以直接傳遞--from all,這樣源節點就是集羣的所有節點,不傳遞該參數的話,則會在遷移過程中提示用戶輸入
                 --cluster-to <arg>            #slot需要遷移的目的節點的node id,目的節點只能填寫一個,不傳遞該參數的話,則會在遷移過程中提示用戶輸入
                 --cluster-slots <arg>         #需要遷移的slot數量,不傳遞該參數的話,則會在遷移過程中提示用戶輸入。
                 --cluster-yes                 #指定遷移時的確認輸入
                 --cluster-timeout <arg>       #設置migrate命令的超時時間
                 --cluster-pipeline <arg>      #定義cluster getkeysinslot命令一次取出的key數量,不傳的話使用默認值爲10
                 --cluster-replace             #是否直接replace到目標節點
  rebalance      host:port                                      #指定集羣的任意一節點進行平衡集羣節點slot數量 
                 --cluster-weight <node1=w1...nodeN=wN>         #指定集羣節點的權重
                 --cluster-use-empty-masters                    #設置可以讓沒有分配slot的主節點參與,默認不允許
                 --cluster-timeout <arg>                        #設置migrate命令的超時時間
                 --cluster-simulate                             #模擬rebalance操作,不會真正執行遷移操作
                 --cluster-pipeline <arg>                       #定義cluster getkeysinslot命令一次取出的key數量,默認值爲10
                 --cluster-threshold <arg>                      #遷移的slot閾值超過threshold,執行rebalance操作
                 --cluster-replace                              #是否直接replace到目標節點
  add-node       new_host:new_port existing_host:existing_port  #添加節點,把新節點加入到指定的集羣,默認添加主節點
                 --cluster-slave                                #新節點作爲從節點,默認隨機一個主節點
                 --cluster-master-id <arg>                      #給新節點指定主節點
  del-node       host:port node_id                              #刪除給定的一個節點,成功後關閉該節點服務
  call           host:port command arg arg .. arg               #在集羣的所有節點執行相關命令
  set-timeout    host:port milliseconds                         #設置cluster-node-timeout
  import         host:port                                      #將外部redis數據導入集羣
                 --cluster-from <arg>                           #將指定實例的數據導入到集羣
                 --cluster-copy                                 #migrate時指定copy
                 --cluster-replace                              #migrate時指定replace
  help           

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

③ 移除一個節點

指定IP、端口和node_id 來刪除一個節點,從節點可以直接刪除,主節點不能直接刪除,刪除之後,該節點會被shutdown。

命令如下所示:

[root@localhost bin]# ./redis-cli --cluster del-node 127.0.0.1:7000 2a470dfa7453c058ae5d92d67e8164026f4a3652
>>> Removing node 2a470dfa7453c058ae5d92d67e8164026f4a3652 from cluster 127.0.0.1:7000
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.

7000的日誌文件如下所示:

19846:S 18 Nov 2019 02:00:16.347 # User requested shutdown...
19846:S 18 Nov 2019 02:00:16.347 * Saving the final RDB snapshot before exiting.
19846:S 18 Nov 2019 02:00:16.354 * DB saved on disk
19846:S 18 Nov 2019 02:00:16.354 * Removing the pid file.
19846:S 18 Nov 2019 02:00:16.354 # Redis is now ready to exit, bye bye...
//可以看到,退出前redis進行了數據保存操作。

④ 查看集羣狀態

命令如下:

[root@localhost bin]# ./redis-cli --cluster info 127.0.0.1:7001 
127.0.0.1:8001 (c57cb1e5...) -> 3 keys | 5461 slots | 0 slaves.
127.0.0.1:8000 (62b73624...) -> 4 keys | 5461 slots | 1 slaves.
127.0.0.1:9000 (49913b6e...) -> 2 keys | 5462 slots | 1 slaves.
[OK] 9 keys in 3 masters.
0.00 keys per slot on average.

⑤ 檢查集羣

命令如下所示:

 ./redis-cli --cluster check 127.0.0.1:7001 --cluster-search-multiple-owners

測試結果如下:

[root@localhost bin]# ./redis-cli --cluster check 127.0.0.1:7001 --cluster-search-multiple-owners
127.0.0.1:8001 (c57cb1e5...) -> 3 keys | 5461 slots | 0 slaves.
127.0.0.1:8000 (62b73624...) -> 4 keys | 5461 slots | 1 slaves.
127.0.0.1:9000 (49913b6e...) -> 2 keys | 5462 slots | 1 slaves.
[OK] 9 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:7001)
S: acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001
   slots: (0 slots) slave
   replicates 49913b6e8c220010d9f02c6b4df56f13cf7524e8
M: c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001
   slots:[0-5460] (5461 slots) master
S: 6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001
   slots: (0 slots) slave
   replicates 62b736242d1ed6f619ae13fbf90da5a737a44449
M: 62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Check for multiple slot owners...

經過了系列操作後,再次查看幾個節點配置文件信息如下所示:

[root@localhost bin]# more nodes-7000.conf
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574061211979 8 connected 5461-10922
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574061213000 7 connected 0-5460
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061210000 6 connected
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 myself,slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213000 1 connected
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213701 8 connected
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574061213000 3 connected 10923-16383
vars currentEpoch 8 lastVoteEpoch 0
[root@localhost bin]# more nodes-7001.conf 
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213621 7 connected
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574061213621 7 connected 0-5460
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 myself,slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213612 2 connected
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061213621 6 connected
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574061213621 3 connected 10923-16383
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574061213621 8 connected 5461-10922
vars currentEpoch 8 lastVoteEpoch 7
[root@localhost bin]# more nodes-8000.conf 
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213698 8 connected
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061213000 6 connected
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574061213000 8 connected 5461-10922
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213000 7 connected
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574061213000 7 connected 0-5460
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 myself,master - 0 1574061213000 3 connected 10923-16383
vars currentEpoch 8 lastVoteEpoch 8
[root@localhost bin]# more nodes-8001.conf 
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574061211069 3 connected 10923-16383
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574061213087 8 connected 5461-10922
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213699 8 connected
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061212080 6 connected
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 myself,master - 0 1574061213000 7 connected 0-5460
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213000 7 connected
vars currentEpoch 8 lastVoteEpoch 8
[root@localhost bin]# more nodes-9000.conf 
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213695 8 connected
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 myself,master - 0 1574061213000 8 connected 5461-10922
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574061213000 3 connected 10923-16383
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061210283 3 connected
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574061213393 7 connected 0-5460
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213000 7 connected
vars currentEpoch 8 lastVoteEpoch 0
[root@localhost bin]# more nodes-9001.conf 
6de2cdb208f73acd7de535a44c8c49f36fc4bdf9 127.0.0.1:9001@19001 myself,slave 62b736242d1ed6f619ae13fbf90da5a737a44449 0 1574061213000 6 connected
49913b6e8c220010d9f02c6b4df56f13cf7524e8 127.0.0.1:9000@19000 master - 0 1574061213000 8 connected 5461-10922
62b736242d1ed6f619ae13fbf90da5a737a44449 127.0.0.1:8000@18000 master - 0 1574061213000 3 connected 10923-16383
c57cb1e504c386e7337eef47dd83278da802ea6f 127.0.0.1:8001@18001 master - 0 1574061211375 7 connected 0-5460
acbcd9e9ff52bf241608f5fbb6dfa081e99ca0db 127.0.0.1:7001@17001 slave 49913b6e8c220010d9f02c6b4df56f13cf7524e8 0 1574061213697 8 connected
2a470dfa7453c058ae5d92d67e8164026f4a3652 127.0.0.1:7000@17000 slave c57cb1e504c386e7337eef47dd83278da802ea6f 0 1574061213393 7 connected
vars currentEpoch 8 lastVoteEpoch 0


【4】創建集羣並手動指定主從關係

先把上面的環境清空,如刪除pid/log/node等信息。

① 創建主節點集羣

命令如下:

./redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:8000 127.0.0.1:9000

測試結果如下:

[root@localhost bin]# ./redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:8000 127.0.0.1:9000
>>> Performing hash slots allocation on 3 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
M: 558b5ed0195dfa34fecb5a06e30141a4c215939e 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
M: 6ea417ccf44da7ce702b346d41952b259196be9f 127.0.0.1:8000
   slots:[5461-10922] (5462 slots) master
M: 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 127.0.0.1:9000
   slots:[10923-16383] (5461 slots) master
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 127.0.0.1:7000)
M: 558b5ed0195dfa34fecb5a06e30141a4c215939e 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
M: 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 127.0.0.1:9000
   slots:[10923-16383] (5461 slots) master
M: 6ea417ccf44da7ce702b346d41952b259196be9f 127.0.0.1:8000
   slots:[5461-10922] (5462 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

② 加入從節點並指定主節點

主從關係指定如下所示:

從----->主
7001-->7000
8001-->8000
9001-->9000
  • 添加7001從節點指定到7000主節點上
./redis-cli --cluster add-node 127.0.0.1:7001 127.0.0.1:7000  --cluster-slave  --cluster-master-id  558b5ed0195dfa34fecb5a06e30141a4c215939e 

結果如下所示:

[root@localhost bin]# ./redis-cli --cluster add-node 127.0.0.1:7001 127.0.0.1:7000  --cluster-slave  --cluster-master-id  558b5ed0195dfa34fecb5a06e30141a4c215939e 
>>> Adding node 127.0.0.1:7001 to cluster 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 558b5ed0195dfa34fecb5a06e30141a4c215939e 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
M: 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 127.0.0.1:9000
   slots:[10923-16383] (5461 slots) master
M: 6ea417ccf44da7ce702b346d41952b259196be9f 127.0.0.1:8000
   slots:[5461-10922] (5462 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 127.0.0.1:7001 to make it join the cluster.
Waiting for the cluster to join
..
>>> Configure node as replica of 127.0.0.1:7000.
[OK] New node added correctly.

分別使用命令查看當前集羣狀態:

//查看集羣信息
./redis-cli --cluster info 127.0.0.1:7000
//檢測集羣
./redis-cli --cluster check 127.0.0.1:7001 --cluster-search-multiple-owners

結果如下所示:
在這裏插入圖片描述
查看7001的日誌如下所示:

 # IP address for this node updated to 127.0.0.1
 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
 # Cluster state changed: ok
 * Connecting to MASTER 127.0.0.1:7000
 * MASTER <-> REPLICA sync started
 * Non blocking connect for SYNC fired the event.
 * Master replied to PING, replication can continue...
 * Trying a partial resynchronization (request 9bbb39d172a4464491448b5e49be1b6a01945585:1).
 * Full resync from master: 915d80708067cfe1c1289adf2e7275c50e4bf78e:0
 * Discarding previously cached master state.
 * MASTER <-> REPLICA sync: receiving 175 bytes from master
 * MASTER <-> REPLICA sync: Flushing old data
 * MASTER <-> REPLICA sync: Loading DB in memory
 * MASTER <-> REPLICA sync: Finished with success
 * Background append only file rewriting started by pid 27688
 * AOF rewrite child asks to stop sending diffs.
 * Parent agreed to stop sending diffs. Finalizing AOF...
 * Concatenating 0.00 MB of AOF diff received from parent.
 * SYNC append only file rewrite performed
 * AOF rewrite: 4 MB of memory used by copy-on-write
 * Background AOF rewrite terminated with success
 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
 * Background AOF rewrite finished successfully

上面標明7001已經成功加入集羣並作爲7000的slaver,同樣可以使用客戶端命令測試如下:

[root@localhost bin]# ./redis-cli -c -p 7000
127.0.0.1:7000> keys *
(empty list or set)
127.0.0.1:7000> set k1 1
-> Redirected to slot [12706] located at 127.0.0.1:9000
OK
127.0.0.1:9000> set k2 2
-> Redirected to slot [449] located at 127.0.0.1:7000
OK
127.0.0.1:7000> exit
[root@localhost bin]# ./redis-cli -p 7001
127.0.0.1:7001> keys *
1) "k2"
127.0.0.1:7001> 

  • 添加8001從節點指定到8000主節點上
./redis-cli --cluster add-node 127.0.0.1:8001 127.0.0.1:8000  --cluster-slave  --cluster-master-id  6ea417ccf44da7ce702b346d41952b259196be9f 
  • 添加9001從節點指定到9000主節點上
./redis-cli --cluster add-node 127.0.0.1:9001 127.0.0.1:9000  --cluster-slave  --cluster-master-id  7f2189d54d4b3fd40da05d6f6698be12fe38f5a8

再次檢查集羣狀態如下:

[root@localhost bin]# ./redis-cli --cluster check 127.0.0.1:7001 --cluster-search-multiple-owners
127.0.0.1:9000 (7f2189d5...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:8000 (6ea417cc...) -> 0 keys | 5462 slots | 1 slaves.
127.0.0.1:7000 (558b5ed0...) -> 1 keys | 5461 slots | 1 slaves.
[OK] 2 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:7001)
S: 306a04d56a000ae194c5bb41f1cbad606f8c1408 127.0.0.1:7001
   slots: (0 slots) slave
   replicates 558b5ed0195dfa34fecb5a06e30141a4c215939e
S: a342ac4a22113e728825af905ca3c333d8f9f1ef 127.0.0.1:8001
   slots: (0 slots) slave
   replicates 6ea417ccf44da7ce702b346d41952b259196be9f
S: ed36b7098a0dfeee66dfc480d32bb40992b268f2 127.0.0.1:9001
   slots: (0 slots) slave
   replicates 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8
M: 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 127.0.0.1:9000
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 6ea417ccf44da7ce702b346d41952b259196be9f 127.0.0.1:8000
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 558b5ed0195dfa34fecb5a06e30141a4c215939e 127.0.0.1:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Check for multiple slot owners...
[root@localhost bin]# ./redis-cli --cluster info 127.0.0.1:7000
127.0.0.1:7000 (558b5ed0...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:9000 (7f2189d5...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:8000 (6ea417cc...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 2 keys in 3 masters.
0.00 keys per slot on average.

查看7000的節點配置文件(bin/nodes-7000.conf):

[root@localhost bin]# more nodes-7000.conf 
7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 127.0.0.1:9000@19000 master - 0 1574077063000 3 connected 10923-16383
306a04d56a000ae194c5bb41f1cbad606f8c1408 127.0.0.1:7001@17001 slave 558b5ed0195dfa34fecb5a06e30141a4c215939e 0 1574077064542 1 connected
ed36b7098a0dfeee66dfc480d32bb40992b268f2 127.0.0.1:9001@19001 slave 7f2189d54d4b3fd40da05d6f6698be12fe38f5a8 0 1574077065553 3 connected
558b5ed0195dfa34fecb5a06e30141a4c215939e 127.0.0.1:7000@17000 myself,master - 0 1574077062000 1 connected 0-5460
a342ac4a22113e728825af905ca3c333d8f9f1ef 127.0.0.1:8001@18001 slave 6ea417ccf44da7ce702b346d41952b259196be9f 0 1574077062526 2 connected
6ea417ccf44da7ce702b346d41952b259196be9f 127.0.0.1:8000@18000 master - 0 1574077063532 2 connected 5461-10922
vars currentEpoch 3 lastVoteEpoch 0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章