redis cluster(2)- 集羣常用命令

 

集羣(cluster)  :這些命令是集羣所獨有的。執行上述命令要先登錄

#查看redis集羣信息:
redis-cli -c -p 6379 cluster nodes
或者
redis-trib.rb  check  10.26.25.115:6379
redis-trib.rb info 10.26.25.115:6379

1、查看集羣:


CLUSTER INFO 打印集羣的信息  

CLUSTER NODES 列出集羣當前已知的所有節點(node),以及這些節點的相關信息。   

redis-cli -c -p 6379 cluster nodes
redis-cli -c -p 6379 cluster info

redis-trib.rb  check  10.26.25.115:6379
redis-trib.rb info 10.26.25.115:6379

 

2、節點(node)  命令


1、加入節點:將 ip 和 port 所指定的節點添加到集羣當中,讓它成爲集羣的一份子。  

1)CLUSTER MEET <ip> <port> 

2)redis-trib.rb add-node <ip> <port>  10.25.157.78:7022 

例如:新增節點:10.80.82.74:7029

redis-trib.rb add-node 10.80.82.74:7029 10.25.157.78:7022 

2、移除節點:

1)、登陸集羣任意節點:執行:CLUSTER FORGET <node_id> 

2)、redis-trib.rb del-node  <ip> <port>  <node_id>

例如

redis-trib.rb del-node 10.80.82.74:7030 923e869b3fda8add429fb200ea00ce94bdbc84e6

CLUSTER FORGET 923e869b3fda8add429fb200ea00ce94bdbc84e6

3、設置主從節點:

CLUSTER REPLICATE <node_id> 將當前節點設置爲 node_id 指定的節點的從節點。  

4、節點數據備份到硬盤:

CLUSTER SAVECONFIG 將節點的配置文件保存到硬盤裏面。   

 

3、槽(slot命令


CLUSTER ADDSLOTS <slot> [slot ...] 將一個或多個槽(slot)指派(assign)給當前節點。  

CLUSTER DELSLOTS <slot> [slot ...] 移除一個或多個槽對當前節點的指派。  

CLUSTER FLUSHSLOTS 移除指派給當前節點的所有槽,讓當前節點變成一個沒有指派任何槽的節點。  

CLUSTER SETSLOT <slot> NODE <node_id> 將槽 slot 指派給 node_id 指定的節點,如果槽已經指派給另一個節點,那麼先讓另一個節點刪除該槽>,然後再進行指派。  

CLUSTER SETSLOT <slot> MIGRATING <node_id> 將本節點的槽 slot 遷移到 node_id 指定的節點中。  

CLUSTER SETSLOT <slot> IMPORTING <node_id> 從 node_id 指定的節點中導入槽 slot 到本節點。  

CLUSTER SETSLOT <slot> STABLE 取消對槽 slot 的導入(import)或者遷移(migrate)。   

 

4、鍵 (key) 命令


CLUSTER KEYSLOT <key> 計算鍵 key 應該被放置在哪個槽上。  

CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的鍵值對數量。  

CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 個 slot 槽中的鍵。  

 

5、redis cluster管理工具redis-trib.rb詳解


redis-trib.rb是redis官方推出的管理redis集羣的工具,集成在redis的源碼src目錄下,是基於redis提供的集羣命令封裝成簡單、便捷、實用的操作工具。

可以通過redis-trib.rb的help信息,看下redis-trib.rb提供了哪些功能。可以看到redis-trib.rb具有以下功能:
1、create:創建集羣
2、check:檢查集羣
3、info:查看集羣信息
4、fix:修復集羣
5、reshard:在線遷移slot
6、rebalance:平衡集羣節點slot數量
7、add-node:將新節點加入集羣
8、del-node:從集羣中刪除節點
9、set-timeout:設置集羣節點間心跳連接的超時時間
10、call:在集羣全部節點上執行命令
11、import:將外部redis數據導入集羣
下面從redis-trib.rb使用和源碼的角度詳細介紹redis-trib.rb的每個功能。

 

create創建集羣

  • create
  • --replicas # 可選參數,replicas表示每個master需要有幾個slave。

create命令可選replicas參數,replicas表示需要有幾個slave。最簡單命令使用如下:

$redis-trib.rb create 10.180.157.199:6379 10.180.157.200:6379 10.180.157.201:6379
有一個slave的創建命令如下:
$ruby redis-trib.rb create --replicas 1 10.180.157.199:6379 10.180.157.200:6379 10.180.157.201:6379 10.180.157.202:6379  10.180.157.205:6379  10.180.157.208:6379 
 

check檢查集羣


檢查集羣狀態的命令,沒有其他參數,只需要選擇一個集羣中的一個節點即可。執行命令以及結果如下:
$ruby redis-trib.rb check 10.180.157.199:6379

檢查前會先執行load_cluster_info_from_node方法,把所有節點數據load進來。load的方式爲通過自己的cluster nodes發現其他節點,然後連接每個節點,並加入nodes數組。接着生成節點間的複製關係。
load完數據後,開始檢查數據,檢查的方式也是調用創建時候使用的check_cluster。
 

info查看集羣信息


info命令用來查看集羣的信息。info命令也是先執行load_cluster_info_from_node獲取完整的集羣信息。然後顯示ClusterNode的info_string結果,示例如下:

$redis-trib.rb info 10.180.157.199:6379

 

fix修復集羣


fix命令的流程跟check的流程很像,顯示加載集羣信息,然後在check_cluster方法內傳入fix爲
true的變量,會在集羣檢查出現異常的時候執行修復流程。目前fix命令能修復兩種異常,一種是集羣有處於遷移中的slot的節點,一種是slot未完全分配的異常。

fix_open_slot方法是修復集羣有處於遷移中的slot的節點異常。
1、先檢查該slot是誰負責的,遷移的源節點如果沒完成遷移,owner還是該節點。沒有owner的slot無法完成修復功能。
2、遍歷每個節點,獲取哪些節點標記該slot爲migrating狀態,哪些節點標記該slot爲importing狀態。對於owner不是該節點,但是通過cluster countkeysinslot獲取到該節點有數據的情況,也認爲該節點爲importing狀態。
3、如果migrating和importing狀態的節點均只有1個,這可能是遷移過程中redis-trib.rb被中斷所致,直接執行move_slot繼續完成遷移任務即可。傳遞dots和fix爲true。
4、如果migrating爲空,importing狀態的節點大於0,那麼這種情況執行回滾流程,將importing狀態的節點數據通過move_slot方法導給slot的owner節點,傳遞dots、fix和cold爲true。接着對importing的節點執行cluster stable命令恢復穩定。
5、如果importing狀態的節點爲空,有一個migrating狀態的節點,而且該節點在當前slot沒有數據,那麼可以直接把這個slot設爲stable。
6、如果migrating和importing狀態不是上述情況,目前redis-trib.rb工具無法修復,上述的三種情況也已經覆蓋了通過redis-trib.rb工具遷移出現異常的各個方面,人爲的異常情形太多,很難考慮完全。
fix_slots_coverage方法能修復slot未完全分配的異常。未分配的slot有三種狀態。

1、所有節點的該slot都沒有數據。該狀態redis-trib.rb工具直接採用隨機分配的方式,並沒有考慮節點的均衡。本人嘗試對沒有分配slot的集羣通過fix修復集羣,結果slot還是能比較平均的分配,但是沒有了連續性,打印的slot信息非常離散。
2、有一個節點的該slot有數據。該狀態下,直接把slot分配給該slot有數據的節點。
3、有多個節點的該slot有數據。此種情況目前還處於TODO狀態,不過redis作者列出了修復的步驟,對這些節點,除第一個節點,執行cluster migrating命令,然後把這些節點的數據遷移到第一個節點上。清除migrating狀態,然後把slot分配給第一個節點。
 

reshard在線遷移slot


reshard命令可以在線把集羣的一些slot從集羣原來slot負責節點遷移到新的節點,利用reshard可以完成集羣的在線橫向擴容和縮容。
reshard的參數很多,下面來一一解釋一番:
reshard      host:port
                --from <arg>
                --to <arg>
                --slots <arg>
                --yes
                --timeout <arg>
                --pipeline <arg>
host:port:這個是必傳參數,用來從一個節點獲取整個集羣信息,相當於獲取集羣信息的入口。
--from <arg>:需要從哪些源節點上遷移slot,可從多個源節點完成遷移,以逗號隔開,傳遞的是節點的node id,還可以直接傳遞--from all,這樣源節點就是集羣的所有節點,不傳遞該參數的話,則會在遷移過程中提示用戶輸入。

--to <arg>:slot需要遷移的目的節點的node id,目的節點只能填寫一個,不傳遞該參數的話,則會在遷移過程中提示用戶輸入。
--slots <arg>:需要遷移的slot數量,不傳遞該參數的話,則會在遷移過程中提示用戶輸入。
--yes:設置該參數,可以在打印執行reshard計劃的時候,提示用戶輸入yes確認後再執行reshard。
--timeout <arg>:設置migrate命令的超時時間。
--pipeline <arg>:定義cluster getkeysinslot命令一次取出的key數量,不傳的話使用默認值爲10。
遷移的流程如下:

1、通過load_cluster_info_from_node方法裝載集羣信息。
2、執行check_cluster方法檢查集羣是否健康。只有健康的集羣才能進行遷移。
3、獲取需要遷移的slot數量,用戶沒傳遞--slots參數,則提示用戶手動輸入。
4、獲取遷移的目的節點,用戶沒傳遞--to參數,則提示用戶手動輸入。此處會檢查目的節點必須爲master節點。
5、獲取遷移的源節點,用戶沒傳遞--from參數,則提示用戶手動輸入。此處會檢查源節點必須爲master節點。--from all的話,源節點就是除了目的節點外的全部master節點。這裏爲了保證集羣slot分配的平均,建議傳遞--from all。
6、執行compute_reshard_table方法,計算需要遷移的slot數量如何分配到源節點列表,採用的算法是按照節點負責slot數量由多到少排序,計算每個節點需要遷移的slot的方法爲:遷移slot數量 * (該源節點負責的slot數量 / 源節點列表負責的slot總數)。這樣算出的數量可能不爲整數,這裏代碼用了下面的方式處理:

n = (numslots/source_tot_slots*s.slots.length)
if i == 0
    n = n.ceil
else
    n = n.floor
這樣的處理方式會帶來最終分配的slot與請求遷移的slot數量不一致,這個BUG已經在github上提給作者,https://github.com/antirez/redis/issues/2990。

7、打印出reshard計劃,如果用戶沒傳--yes,就提示用戶確認計劃。
8、根據reshard計劃,一個個slot的遷移到新節點上,遷移使用move_slot方法,該方法被很多命令使用,具體可以參見下面的遷移流程。move_slot方法傳遞dots爲true和pipeline數量。
9、至此,就完成了全部的遷移任務。
下面看下一次reshard的執行結果:
$ruby redis-trib.rb reshard --from all --to 80b661ecca260c89e3d8ea9b98f77edaeef43dcd --slots 11 10.180.157.199:6379

Ready to move 11 slots.
Moving slot 5461 from e36c46dbe90960f30861af00786d4c2064e63df2

。。。
Moving slot 10923 from 10.180.157.201:6379 to 10.180.157.200:6380:
Moving slot 10924 from 10.180.157.201:6379 to 10.180.157.200:6380:
Moving slot 10925 from 10.180.157.201:6379 to 10.180.157.200:6380:
move_slot方法可以在線將一個slot的全部數據從源節點遷移到目的節點,fix、reshard、rebalance都需要調用該方法遷移slot。

move_slot接受下面幾個參數:
1、pipeline:設置一次從slot上獲取多少個key。
2、quiet:遷移會打印相關信息,設置quiet參數,可以不用打印這些信息。
3、cold:設置cold,會忽略執行importing和migrating。
4、dots:設置dots,則會在遷移過程打印遷移key數量的進度。
5、update:設置update,則會更新內存信息,方便以後的操作。
move_slot流程如下:

1、如果沒有設置cold,則對源節點執行cluster importing命令,對目的節點執行migrating命令。fix的時候有可能importing和migrating已經執行過來,所以此種場景會設置cold。
2、通過cluster getkeysinslot命令,一次性獲取遠節點遷移slot的pipeline個key的數量.
3、對這些key執行migrate命令,將數據從源節點遷移到目的節點。
4、如果migrate出現異常,在fix模式下,BUSYKEY的異常,會使用migrate的replace模式再執行一次,BUSYKEY表示目的節點已經有該key了,replace模式可以強制替換目的節點的key。不是fix模式就直接返回錯誤了。
5、循環執行cluster getkeysinslot命令,直到返回的key數量爲0,就退出循環。
6、如果沒有設置cold,對每個節點執行cluster setslot命令,把slot賦給目的節點。
7、如果設置update,則修改源節點和目的節點的slot信息。
8、至此完成了遷移slot的流程。
 

rebalance平衡集羣節點slot數量


rebalance命令可以根據用戶傳入的參數平衡集羣節點的slot數量,rebalance功能非常強大,可以傳入的參數很多,以下是rebalance的參數列表和命令示例。

rebalance       host:port
                --weight <arg>
                --auto-weights
                --threshold <arg>
                --use-empty-masters
                --timeout <arg>
                --simulate
                --pipeline <arg>

$ruby redis-trib.rb rebalance --threshold 1 --weight b31e3a2e=5 --weight 60b8e3a1=5 --use-empty-masters  --simulate 10.180.157.199:6379
下面也先一一解釋下每個參數的用法:

host:port:這個是必傳參數,用來從一個節點獲取整個集羣信息,相當於獲取集羣信息的入口。
--weight <arg>:節點的權重,格式爲node_id=weight,如果需要爲多個節點分配權重的話,需要添加多個--weight <arg>參數,即--weight b31e3a2e=5 --weight 60b8e3a1=5,node_id可爲節點名稱的前綴,只要保證前綴位數能唯一區分該節點即可。沒有傳遞–weight的節點的權重默認爲1。
--auto-weights:這個參數在rebalance流程中並未用到。
--threshold <arg>:只有節點需要遷移的slot閾值超過threshold,纔會執行rebalance操作。具體計算方法可以參考下面的rebalance命令流程的第四步。
--use-empty-masters:rebalance是否考慮沒有節點的master,默認沒有分配slot節點的master是不參與rebalance的,設置--use-empty-masters可以讓沒有分配slot的節點參與rebalance。
--timeout <arg>:設置migrate命令的超時時間。
--simulate:設置該參數,可以模擬rebalance操作,提示用戶會遷移哪些slots,而不會真正執行遷移操作。
--pipeline <arg>:與reshar的pipeline參數一樣,定義cluster getkeysinslot命令一次取出的key數量,不傳的話使用默認值爲10。
rebalance命令流程如下:

1、load_cluster_info_from_node方法先加載集羣信息。
2、計算每個master的權重,根據參數--weight <arg>,爲每個設置的節點分配權重,沒有設置的節點,則權重默認爲1。
3、根據每個master的權重,以及總的權重,計算自己期望被分配多少個slot。計算的方式爲:總slot數量 * (自己的權重 / 總權重)。
4、計算每個master期望分配的slot是否超過設置的閾值,即--threshold <arg>設置的閾值或者默認的閾值。計算的方式爲:先計算期望移動節點的閾值,算法爲:(100-(100.0*expected/n.slots.length)).abs,如果計算出的閾值沒有超出設置閾值,則不需要爲該節點移動slot。只要有一個master的移動節點超過閾值,就會觸發rebalance操作。
5、如果觸發了rebalance操作。那麼就開始執行rebalance操作,先將每個節點當前分配的slots數量減去期望分配的slot數量獲得balance值。將每個節點的balance從小到大進行排序獲得sn數組。
6、用dst_idx和src_idx遊標分別從sn數組的頭部和尾部開始遍歷。目的是爲了把尾部節點的slot分配給頭部節點。

sn數組保存的balance列表排序後,負數在前面,正數在後面。負數表示需要有slot遷入,所以使用dst_idx遊標,正數表示需要有slot遷出,所以使用src_idx遊標。理論上sn數組各節點的balance值加起來應該爲0,不過由於在計算期望分配的slot的時候只是使用直接取整的方式,所以可能出現balance值之和不爲0的情況,balance值之和不爲0即爲節點不平衡的slot數量,由於slot總數有16384個,不平衡數量相對於總數,基數很小,所以對rebalance流程影響不大。

7、獲取sn[dst_idx]和sn[src_idx]的balance值較小的那個值,該值即爲需要從sn[src_idx]節點遷移到sn[dst_idx]節點的slot數量。
8、接着通過compute_reshard_table方法計算源節點的slot如何分配到源節點列表。這個方法在reshard流程中也有調用,具體步驟可以參考reshard流程的第六步。
9、如果是simulate模式,則只是打印出遷移列表。
10、如果沒有設置simulate,則執行move_slot操作,遷移slot,傳入的參數爲:quiet=>true,:dots=>false,:update=>true。
11、遷移完成後更新sn[dst_idx]和sn[src_idx]的balance值。如果balance值爲0後,遊標向前進1。
12、直到dst_idx到達src_idx遊標,完成整個rebalance操作。
 

add-node將新節點加入集羣


add-node命令可以將新節點加入集羣,節點可以爲master,也可以爲某個master節點的slave。

add-node    new_host:new_port existing_host:existing_port
          --slave
          --master-id <arg>
add-node有兩個可選參數:

--slave:設置該參數,則新節點以slave的角色加入集羣
--master-id:這個參數需要設置了--slave才能生效,--master-id用來指定新節點的master節點。如果不設置該參數,則會隨機爲節點選擇master節點。
可以看下add-node命令的執行示例:

$redis-trib.rb add-node --slave --master-id dcb792b3e85726f012e83061bf237072dfc45f99 10.180.157.202:6379 10.180.157.199:6379
add-node流程如下:
1、通過load_cluster_info_from_node方法轉載集羣信息,check_cluster方法檢查集羣是否健康。
2、如果設置了--slave,則需要爲該節點尋找master節點。設置了--master-id,則以該節點作爲新節點的master,如果沒有設置--master-id,則調用get_master_with_least_replicas方法,尋找slave數量最少的master節點。如果slave數量一致,則選取load_cluster_info_from_node順序發現的第一個節點。load_cluster_info_from_node順序的第一個節點是add-node設置的existing_host:existing_port節點,後面的順序根據在該節點執行cluster nodes返回的結果返回的節點順序。
3、連接新的節點並與集羣第一個節點握手。
4、如果沒設置–slave就直接返回ok,設置了–slave,則需要等待確認新節點加入集羣,然後執行cluster replicate命令複製master節點。
5、至此,完成了全部的增加節點的流程。
 

del-node從集羣中刪除節點


del-node可以把某個節點從集羣中刪除。del-node只能刪除沒有分配slot的節點。刪除命令傳遞兩個參數:

host:port:從該節點獲取集羣信息。
node_id:需要刪除的節點id。
del-node執行結果示例如下:

$redis-trib.rb del-node 10.180.157.199:6379 d5f6d1d17426bd564a6e309f32d0f5b96962fe53

del-node流程如下:

1、通過load_cluster_info_from_node方法轉載集羣信息。
2、根據傳入的node id獲取節點,如果節點沒找到,則直接提示錯誤並退出。
3、如果節點分配的slot不爲空,則直接提示錯誤並退出。
4、遍歷集羣內的其他節點,執行cluster forget命令,從每個節點中去除該節點。如果刪除的節點是master,而且它有slave的話,這些slave會去複製其他master,調用的方法是get_master_with_least_replicas,與add-node沒設置--master-id尋找master的方法一樣。

5、然後關閉該節點

 

set-timeout設置集羣節點間心跳連接的超時時間

set-timeout用來設置集羣節點間心跳連接的超時時間,單位是毫秒,不得小於100毫秒,因爲100毫秒對於心跳時間來說太短了。該命令修改是節點配置參數cluster-node-timeout,默認是15000毫秒。通過該命令,可以給每個節點設置超時時間,設置的方式使用config set命令動態設置,然後執行config rewrite命令將配置持久化保存到硬盤。以下是示例:

$redis-trib.rb set-timeout 10.180.157.199:6379 30000

 

call在集羣全部節點上執行命令


call命令可以用來在集羣的全部節點執行相同的命令。call命令也是需要通過集羣的一個節點地址,連上整個集羣,然後在集羣的每個節點執行該命令。

$ redis-trib.rb call 10.180.157.199:6379 get key

 

import將外部redis數據導入集羣


import命令可以把外部的redis節點數據導入集羣。導入的流程如下:

1、通過load_cluster_info_from_node方法轉載集羣信息,check_cluster方法檢查集羣是否健康。
2、連接外部redis節點,如果外部節點開啓了cluster_enabled,則提示錯誤。
3、通過scan命令遍歷外部節點,一次獲取1000條數據。
4、遍歷這些key,計算出key對應的slot。
5、執行migrate命令,源節點是外部節點,目的節點是集羣slot對應的節點,如果設置了--copy參數,則傳遞copy參數,如果設置了--replace,則傳遞replace參數。
6、不停執行scan命令,直到遍歷完全部的key。
7、至此完成整個遷移流程
這中間如果出現異常,程序就會停止。沒使用--copy模式,則可以重新執行import命令,使用--copy的話,最好清空新的集羣再導入一次。
 

import命令更適合離線的把外部redis數據導入,在線導入的話最好使用更專業的導入工具,以slave的方式連接redis節點去同步節點數據應該是更好的方式。

下面是一個例子

./redis-trib.rb import --from 10.0.10.1:6379 10.10.10.1:7000
上面的命令是把 10.0.10.1:6379(redis 2.8)上的數據導入到 10.10.10.1:7000這個節點所在的集羣

  

宕機情況

  • 當某個從節點掛掉之後,對於redis集羣來說幾乎沒有什麼影響,相當於這個從節點對應的 主節點少了一個備份而已。
  • 當某一個主節點掛掉之後,redis 會從這個 主節點 的 多個從節點 中推選一個出來,擔當master的工作,並且把之前依附在
  • 主節點的從節點調整依附到新的master上。如果新任的master也掛掉並且他沒有從節點了,那麼這個集羣也真正的掛掉了。

集羣創建時 replicas 參數 指定情況。

  • 使用 --replicas 1 參數時,如果節點數量少於六個。
    報錯
    *** ERROR: Invalid configuration for cluster creation.
    *** Redis Cluster requires at least 3 master nodes.
    *** This is not possible with 5 nodes and 1 replicas per node.
    *** At least 6 nodes are required.
  • 使用 --replicas 1 參數時,如果節點數量 大於六個,且爲單數時。
    這樣會造成某個master擁有兩個salve


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章