[redis] redis在線系統熱遷移的方案與記錄
一 前言
如圖,是我的環境。
這里邊有三個系統,1 業務系統。2 redis cluster集群。3 redis cluster集群的管理系統。
系統1,會對redis中進行秒級的數據添加,讀取,刪除操作。系統3,是redis集群的增加節點減少節點,節點failover功能進行管理。
如圖目前,我的系統里,redis共占用了a1,b1,c1,d1四臺物理設備。我的目的是,在不影響業務系統運行的情況下,
將redis集群遷移到a2,b2,c2,d2四臺物理設備上去。

二 預備知識
目標系統的redis版本是4.0,之所以強調版本,是因為新版本中,擁有了命令
redis-cli --cluster。4.0版本中并沒有,它的前任是腳本,redis-trib.rb。二者
大同小異,沒有本質區別。
下面是,進行中使用到的幾個操作
1. 查看當前集群拓撲的方法
redis-cli -c cluster nodes redis-cli -c cluster slots
拓撲關系
a51459f9cf9b5611cefe137dfcfbd9d9fdb03cfe 10.1.3.168:6379@16379 slave c3ac54ffd1efd366fdf70b3ba0e4185bee49840e 0 1584705659599 6 connected 8ea700c80aa9bebbcd87549cad4538cfeb13dc5f 10.1.4.40:6379@16379 master - 0 1584705662628 1 connected 0-5460 d1fb28322822546c76800cee00fc08ea30eee3d9 10.1.4.39:6379@16379 slave 38dcb1adf11ca19bc66d2d2e887588fb65537c9e 0 1584705658000 4 connected f4f3aa15073de7f6efc0ee104d4b51de8d5e5ff5 10.1.3.165:6379@16379 slave 8ea700c80aa9bebbcd87549cad4538cfeb13dc5f 0 1584705660606 5 connected 38dcb1adf11ca19bc66d2d2e887588fb65537c9e 10.1.3.170:6379@16379 myself,master - 0 1584705659000 3 connected 10923-16383 c3ac54ffd1efd366fdf70b3ba0e4185bee49840e 10.1.3.169:6379@16379 master - 0 1584705661622 2 connected 5461-10922
2 查看數據分布的方法
redis-trib.rb info 127.0.0.1:6379
數據分別是指,那些數據存儲在那些節點上。
我這里的集群組織方式是,一對一對的組織。每一對有一個master,一個slave。slave作為master的數據冗余和failover節點??梢詮纳弦粋€命令的輸出里,見到他們的關系,
而,數據的分布如下所示,關注keys信息??梢钥匆?,那些那些key,在那些那些地方。當正在進行數據遷移時,我們能看見keys前邊的數值在一點點減少。
[root@redis6st caotong]# redis-trib.rb info 127.0.0.1:6379 127.0.0.1:6379 (38dcb1ad...) -> 1998 keys | 5461 slots | 1 slaves. 10.1.4.40:6379 (8ea700c8...) -> 2012 keys | 5461 slots | 1 slaves. 10.1.3.169:6379 (c3ac54ff...) -> 1999 keys | 5462 slots | 1 slaves. [OK] 6009 keys in 3 masters. 0.37 keys per slot on average.
3 查看集群實時狀態的方法
redis-trib.rb check 127.0.0.1:6379
這個輸出,重點關心的是一下額外的信息, 如xxx is migrating 字樣
[root@redis6st caotong]# redis-trib.rb check 127.0.0.1:6379 >>> Performing Cluster Check (using node 127.0.0.1:6379) M: 38dcb1adf11ca19bc66d2d2e887588fb65537c9e 127.0.0.1:6379 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: a51459f9cf9b5611cefe137dfcfbd9d9fdb03cfe 10.1.3.168:6379 slots: (0 slots) slave replicates c3ac54ffd1efd366fdf70b3ba0e4185bee49840e M: 8ea700c80aa9bebbcd87549cad4538cfeb13dc5f 10.1.4.40:6379 slots:0-5460 (5461 slots) master 1 additional replica(s) S: d1fb28322822546c76800cee00fc08ea30eee3d9 10.1.4.39:6379 slots: (0 slots) slave replicates 38dcb1adf11ca19bc66d2d2e887588fb65537c9e S: f4f3aa15073de7f6efc0ee104d4b51de8d5e5ff5 10.1.3.165:6379 slots: (0 slots) slave replicates 8ea700c80aa9bebbcd87549cad4538cfeb13dc5f M: c3ac54ffd1efd366fdf70b3ba0e4185bee49840e 10.1.3.169: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.
三 思路
兩個思路。
1,把集群節點遷走,集群還是那個集群只不過他們的各種節點都被更新了。
2,把數據遷走,幸運的是我的業務系統有重連機制,并且支持熱修改集群信息。所以只要保證數據的增刪改查都能成功并正確。切換一個全新的cluster同樣對業務無感知。
四 方案一
我這里,采用的遷移方案,是先擴容再縮容。這樣是熱的,online的。對在線系統無感知的。
把你想遷入的目標作為擴容資源擴進來,然后再將你想縮容的資源作為遷出目標縮掉,即可。
我會先增加一對主備節點,然后理由上面提到的兩個命令,來觀察:
(1)遷移的過程是否正常,(2)數據是否正常流動,(3)遷移是否已經進行完成
遷移進行完成指的是數據流動已經完成。
過程是否正常:1 通過前文的check命令查看runtime狀態。2.通過info命名查看數據流動進程。
最終的狀態,可以通過nodes命令觀察,是否出現fail的節點。以及是否每個master都結對一個slave,
包括誰和誰是一對的這種對應關系。
增減動作通過前文中的管理系統接口完成的,沒有命令的細節。 該系統只是對redis -cli和redis-trib.rb的封裝,
附加了他自己的邏輯在里邊。
redis-cli --cluster help可以看見更多細節,包括add node,add slot之類的常用命令。
刪除一個節點的方法:
redis-trib.rb del-node host:port node_id
參考: http://www.rzrgm.cn/ivictor/p/9768010.html
然而,該方案并沒有實施成功,因為該管理系統的bug,導致其自己進入不可跳出的管理狀態里。
這里不在贅述,進入方案二
五 方案二
如前文述,方案二的思路是數據遷移。管理系統在節點變更是存在問題。但是全新創建的話,仍然是可用的。
于是,現在我們可用繞可它來達到目標。
需要強調的是,本人是新手,完成100臺以下的數據遷移工作只有三天時間,并之前幾乎沒有好好接觸過redis。
所以整體目標是安全與快速。故選用以下四個方法,并排列優先級:
可選有四種方法,要求必須滿足online的數據無縫熱遷移:
1 python工具:https://github.com/p/redis-dump-load
該工具簡單使用后發現不支持集群,只支持單點設備。工作量大,留做備選。
2 ruby工具: https://github.com/delano/redis-dump
該工具測試之后發現有一個bug。用的話,需要修復一下bug。會增加額外工作,留作備選。報錯如下
CROSSSLOT Keys in request don't hash to the same slot redis dump
另外,這個東西安裝有點麻煩,還有安裝ruby環境。安裝ruby的環境與包管理工具的方法:
yum install rubygems
3 C工具:https://github.com/tanruixing88/redis-migrate-tool
該方法可以。并最后成功了。后邊詳述。另,這是唯品會工具的一個fork,說是唯品會的只支持3.0,這個支持高版本,見:
https://cco.xyz/post/redis-migrae-tool/
4 RDB與AOF方案:使用bgsave命令,已經修改配置文件等方法。
這是保底方案,是官方正規方法,并且一點可以成功。但是很顯然更花時間。有額外的學習成本,也有額外的時間成本。
redis-migrate-tool的詳細操作步驟
1 配置文件: 所有節點的IP + Port,包括slave和master
[source] type: redis cluster servers: - 10.1.0.12:6379 - 10.1.0.6:6379 - 10.1.0.24:6379 - 10.1.0.11:6379 - 10.1.0.5:6379 - 10.1.0.9:6379 - 10.1.0.8:6379 - 10.1.0.7:6379 - 10.1.0.13:6379 - 10.1.0.10:6379 [target] type: redis cluster servers: - 10.1.0.50:6379 - 10.1.0.46:6379 - 10.1.0.48:6379 - 10.1.0.47:6379 - 10.1.0.45:6379 - 10.1.0.51:6379 - 10.1.0.49:6379 - 10.1.0.19:6379 [common] listen: 0.0.0.0:8888
快速生成以上ip串的小技巧:
redis-cli -c cluster nodes |awk '{print $2}' |awk -F'@' '{print "- "$1}'
2 啟動方法:
./redis-migrate-tool -c migrate.conf -o log -d
3 停止方法
使用下面的命令行進入管理界面:
redis-cli -h 127.0.0.1 -p 8888
然后執行shutdown命令。
遷移步驟:
1 新建一個全新的redis 集群,并確保集群建立成功,集群狀態up。
2 配置 redis-migrate-tool工具的配置文件
3 啟動工具,這個時候能觀察到新group中的key書目在不斷增加。直到超過舊集群的key總數。
這里需要說明的時候,因為舊group依然是業務在線的。所以key實際上處于有增有減的動態過程中。而遷移工具實際上做的時候一個不斷copy的工作,
所以,新集群實際上是舊集群里所有key的累加結果。被刪掉的舊集群上的key并不會被一起上新集群里刪掉。
4 這里有兩個假設,
1 遷移工具的遷移速度大于舊集群中key的新增速度。
2 業務系統必須容忍這樣一直失敗場景:剛存入的key,在小于遷移速度的時間內有可能獲取失敗。
在滿足以上兩個條件的前提下,進行第五步操作:
遷移業務系統:使用命令解綁舊的業務系統與redis 集群的綁定關系,綁定新的集群。
6 在第五步完成之后,可以觀察到舊集群中的key數量將不在變化,沒有新的key增加,也沒有舊的key刪除。
再觀察遷移工具,發現全部的key遷移已經完成了。
這塊時候可以停止遷移工具了。
7 刪除舊的集群
8 (4)中提到的那些沒有被刪除的舊key,會在n天后超時自己刪掉自己。
我的業務系統對每一個key丟進行了超時配置。不過即使沒有這個附件條件,依然沒有關系,我們可以通過一下方法來達到這個目的,
以使得我的方案更具有處理一般問題的普適性。
對所有可以,設置超時的方法:
redis-cli -c keys '*yourKEYWORD*' |xargs -l -I {} redis-cli -c set {} 123 ex 3
至此,數據熱遷移完成。對業務無感知。
六 完
[classic_tong @ 20200321 https:////www.rzrgm.cn/hugetong/p/12584107.html]
完。

浙公網安備 33010602011771號