redis cluster管理工具redis-trib.rb詳解
來源 http://weizijun.cn/2016/01/08/redis%20cluster%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7redis-trib-rb%E8%AF%A6%E8%A7%A3/
概述
redis-trib.rb是redis官方推出的管理redis叢集的工具,整合在redis的原始碼src目錄下,是基於redis提供的叢集命令封裝成簡單、便捷、實用的操作工具。redis-trib.rb是redis作者用ruby完成的。為了看懂redis-trib.rb,我特意花了一個星期學習了ruby,也被ruby的簡潔、明瞭所吸引。ruby是門非常靈活的語言,redis-trib.rb只用了1600行左右的程式碼,就實現了強大的叢集操作。本文對redis-trib.rb的介紹是基於redis 3.0.6版本的原始碼。閱讀本文需要對redis叢集功能有一定的瞭解。關於redis叢集功能的介紹,可以參考本人的另一篇文章《redis3.0 cluster功能介紹》。
先從redis-trib.rb的help資訊,看下redis-trib.rb提供了哪些功能。
1
|
$ruby redis-trib.rb help
|
可以看到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的每個功能。
redis-trib.rb主要有兩個類:ClusterNode
和RedisTrib
。ClusterNode
儲存了每個節點的資訊,RedisTrib
則是redis-trib.rb各個功能的實現。
ClusterNode物件
先分析ClusterNode
原始碼。ClusterNode
有下面幾個成員變數(ruby的類成員變數是以@開頭的):
@r
:執行redis命令的客戶端物件。@info
:儲存了該節點的詳細資訊,包括cluster nodes命令中自己這行的資訊和cluster info的資訊。@dirty
:節點資訊是否需要更新,如果為true,我們需要把記憶體的節點更新資訊到節點上。@friends
:儲存了叢集其他節點的info資訊。其資訊為通過cluster nodes命令獲得的其他節點資訊。
ClusterNode
有下面一些成員方法:
initialize
:ClusterNode的構造方法,需要傳入節點的地址資訊。friends
:返回@friends物件。slots
:返回該節點負責的slots資訊。has_flag?
:判斷節點info資訊的的flags中是否有給定的flag。to_s
:類似java的toString方法,返回節點的地址資訊。connect
:連線redis節點。assert_cluster
:判斷節點開啟了叢集配置。assert_empty
:確定節點目前沒有跟任何其他節點握手,同時自己的db資料為空。load_info
:通過cluster info和cluster nodes匯入節點資訊。add_slots
:給節點增加slot,該操作只是在記憶體中修改,並把dirty設定成true,等待flush_node_config將記憶體中的資料同步在節點執行。set_as_replica
:slave設定複製的master地址。dirty設定成true。flush_node_config
:將記憶體的資料修改同步在叢集節點中執行。info_string
:簡單的info資訊。get_config_signature
:用來驗證叢集節點見的cluster nodes資訊是否一致。該方法返回節點的簽名資訊。info
:返回@info物件,包含詳細的info資訊。is_dirty?
:判斷@dirty。r
:返回執行redis命令的客戶端物件。
有了ClusterNode物件,在處理叢集操作的時候,就獲得了叢集的資訊,可以進行叢集相關操作。在此先簡單介紹下redis-trib.rb指令碼的使用,以create為例:
create host1:port1 ... hostN:portN
--replicas <arg>
host1:port1 ... hostN:portN
表示子引數,這個必須在可選引數之後,--replicas <arg>
是可選引數,帶的表示後面必須填寫一個引數,像--slave
這樣,後面就不帶引數,掌握了這個基本規則,就能從help命令中獲得redis-trib.rb的使用方法。
其他命令大都需要傳遞host:port
,這是redis-trib.rb為了連線叢集,需要選擇叢集中的一個節點,然後通過該節點獲得整個叢集的資訊。
下面就一一詳細介紹redis-trib.rb的每個功能。
create建立叢集
create命令可選replicas引數,replicas表示需要有幾個slave。最簡單命令使用如下:
$ruby 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
建立流程如下:
- 1、首先為每個節點建立ClusterNode物件,包括連線每個節點。檢查每個節點是否為獨立且db為空的節點。執行
load_info
方法匯入節點資訊。 - 2、檢查傳入的master節點數量是否大於等於3個。只有大於3個節點才能組成叢集。
- 3、計算每個master需要分配的slot數量,以及給master分配slave。分配的演算法大致如下:
- 先把節點按照host分類,這樣保證master節點能分配到更多的主機中。
- 不停遍歷遍歷host列表,從每個host列表中彈出一個節點,放入interleaved陣列。直到所有的節點都彈出為止。
- master節點列表就是interleaved前面的master數量的節點列表。儲存在masters陣列。
- 計算每個master節點負責的slot數量,儲存在slots_per_node物件,用slot總數除以master數量取整即可。
- 遍歷masters陣列,每個master分配slots_per_node個slot,最後一個master,分配到16384個slot為止。
- 接下來為master分配slave,分配演算法會盡量保證master和slave節點不在同一臺主機上。對於分配完指定slave數量的節點,還有多餘的節點,也會為這些節點尋找master。分配演算法會遍歷兩次masters陣列。
- 第一次遍歷masters陣列,在餘下的節點列表找到replicas數量個slave。每個slave為第一個和master節點host不一樣的節點,如果沒有不一樣的節點,則直接取出餘下列表的第一個節點。
- 第二次遍歷是在對於節點數除以replicas不為整數,則會多餘一部分節點。遍歷的方式跟第一次一樣,只是第一次會一次性給master分配replicas數量個slave,而第二次遍歷只分配一個,直到餘下的節點被全部分配出去。
- 4、列印出分配資訊,並提示使用者輸入“yes”確認是否按照列印出來的分配方式建立叢集。
- 5、輸入“yes”後,會執行flush_nodes_config操作,該操作執行前面的分配結果,給master分配slot,讓slave複製master,對於還沒有握手(cluster meet)的節點,slave複製操作無法完成,不過沒關係,flush_nodes_config操作出現異常會很快返回,後續握手後會再次執行flush_nodes_config。
- 6、給每個節點分配epoch,遍歷節點,每個節點分配的epoch比之前節點大1。
- 7、節點間開始相互握手,握手的方式為節點列表的其他節點跟第一個節點握手。
- 8、然後每隔1秒檢查一次各個節點是否已經訊息同步完成,使用ClusterNode的get_config_signature方法,檢查的演算法為獲取每個節點cluster nodes資訊,排序每個節點,組裝成
node_id1:slots|node_id2:slot2|...
的字串。如果每個節點獲得字串都相同,即認為握手成功。 - 9、此後會再執行一次flush_nodes_config,這次主要是為了完成slave複製操作。
- 10、最後再執行check_cluster,全面檢查一次叢集狀態。包括和前面握手時檢查一樣的方式再檢查一遍。確認沒有遷移的節點。確認所有的slot都被分配出去了。
- 11、至此完成了整個建立流程,返回
[OK] All 16384 slots covered.
。
check檢查叢集
檢查叢集狀態的命令,沒有其他引數,只需要選擇一個叢集中的一個節點即可。執行命令以及結果如下:
$ruby redis-trib.rb check 10.180.157.199:6379
>>> Performing Cluster Check (using node 10.180.157.199:6379)
M: b2506515b38e6bbd3034d540599f4cd2a5279ad1 10.180.157.199:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: d376aaf80de0e01dde1f8cd4647d5ac3317a8641 10.180.157.205:6379
slots: (0 slots) slave
replicates e36c46dbe90960f30861af00786d4c2064e63df2
M: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 59fa6ee455f58a5076f6d6f83ddd74161fd7fb55 10.180.157.208:6379
slots: (0 slots) slave
replicates 15126fb33796c2c26ea89e553418946f7443d5a5
S: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379
slots: (0 slots) slave
replicates b2506515b38e6bbd3034d540599f4cd2a5279ad1
M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379
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.
檢查前會先執行load_cluster_info_from_node方法,把所有節點資料load進來。load的方式為通過自己的cluster nodes發現其他節點,然後連線每個節點,並加入nodes陣列。接著生成節點間的複製關係。
load完資料後,開始檢查資料,檢查的方式也是呼叫建立時候使用的check_cluster。
info檢視叢集資訊
info命令用來檢視叢集的資訊。info命令也是先執行load_cluster_info_from_node獲取完整的叢集資訊。然後顯示ClusterNode的info_string結果,示例如下:
$ruby redis-trib.rb info 10.180.157.199:6379
10.180.157.199:6379 (b2506515...) -> 0 keys | 5461 slots | 1 slaves.
10.180.157.201:6379 (15126fb3...) -> 0 keys | 5461 slots | 1 slaves.
10.180.157.200:6379 (e36c46db...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
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的執行結果:
1
|
$ruby redis-trib.rb reshard --from all --to 80b661ecca260c89e3d8ea9b98f77edaeef43dcd --slots 11 10.180.157.199:6379
|
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命令的執行示例:
$ruby redis-trib.rb add-node --slave --master-id dcb792b3e85726f012e83061bf237072dfc45f99 10.180.157.202:6379 10.180.157.199:6379
>>> Adding node 10.180.157.202:6379 to cluster 10.180.157.199:6379
>>> Performing Cluster Check (using node 10.180.157.199:6379)
M: dcb792b3e85726f012e83061bf237072dfc45f99 10.180.157.199:6379
slots:0-5460 (5461 slots) master
0 additional replica(s)
M: 464d740bf48953ebcf826f4113c86f9db3a9baf3 10.180.157.201:6379
slots:10923-16383 (5461 slots) master
0 additional replica(s)
M: befa7e17b4e5f239e519bc74bfef3264a40f96ae 10.180.157.200:6379
slots:5461-10922 (5462 slots) master
0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 10.180.157.202:6379 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 10.180.157.199:6379.
[OK] New node added correctly.
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執行結果示例如下:
$ruby redis-trib.rb del-node 10.180.157.199:6379 d5f6d1d17426bd564a6e309f32d0f5b96962fe53
>>> Removing node d5f6d1d17426bd564a6e309f32d0f5b96962fe53 from cluster 10.180.157.199:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
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
命令將配置持久化儲存到硬碟。以下是示例:
ruby redis-trib.rb set-timeout 10.180.157.199:6379 30000
>>> Reconfiguring node timeout in every cluster node...
*** New timeout set for 10.180.157.199:6379
*** New timeout set for 10.180.157.205:6379
*** New timeout set for 10.180.157.201:6379
*** New timeout set for 10.180.157.200:6379
*** New timeout set for 10.180.157.208:6379
>>> New node timeout set. 5 OK, 0 ERR.
call在叢集全部節點上執行命令
call命令可以用來在叢集的全部節點執行相同的命令。call命令也是需要通過叢集的一個節點地址,連上整個叢集,然後在叢集的每個節點執行該命令。
$ruby redis-trib.rb call 10.180.157.199:6379 get key
>>> Calling GET key
10.180.157.199:6379: MOVED 12539 10.180.157.201:6379
10.180.157.205:6379: MOVED 12539 10.180.157.201:6379
10.180.157.201:6379:
10.180.157.200:6379: MOVED 12539 10.180.157.201:6379
10.180.157.208:6379: MOVED 12539 10.180.157.201:6379
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節點去同步節點資料應該是更好的方式。