1. 程式人生 > >ip變更造成的redis叢集不可用的解決及資料備份和恢復

ip變更造成的redis叢集不可用的解決及資料備份和恢復

今天開啟電腦,連線redis,發現連線不上了...


原因是找不到主機...檢視虛擬機器ip,發現ip變了...


於是想到之前配置redis叢集的時候,在redis.conf中配置了bind為虛擬機器的ip地址,覺得應該是這個原因,於是修

配置bind:127.0.0.1,重啟叢集,想想應該是沒問題了,但是...



服務啟起來了,ip也顯示為127.0.0.1,但是進行check的時候報了異常,can't connect to node 192.168.21.128...是的 

連的還是舊的ip...設定了bind屬性貌似不起作用,於是嘗試去查詢資料,沒有找到解決方案,感覺是叢集已經被我玩壞了,

其實仔細一想redis一定是把一些引數儲存在了其叢集的配置檔案中,

check的時候是去配置檔案中讀取ip的。

如下圖,進入其中一個節點的配置檔案:


appendonly.aof和dump.rdb是持久化的資料備份檔案,redis.conf是配置檔案,redis-server及redis-cli是執行redis啟動,

連線等操作的指令碼,nodes-8001.conf和redis.pid分別對應redis.conf中的cluster-config-file和pidfile屬性,猜想應該是和

這兩個檔案有關係,有兩個解決方案,第一研究原始碼,去修改兩個檔案中的相關配置,可能會出現不可預知的問題,

第二個方案重新搭建叢集,簡單粗暴但是一定有效,當然前提是對資料做好備份。我選擇了第二種,順便能搞下資料

的恢復。首先新建一個資料夾,將備份檔案移過去,之後將除redis.conf,redis-cli和redis-server以外的檔案全部移除



這個時候的叢集配置應該已經完全沒了,嘗試重新搭建叢集






此時的幾個redis服務都沒有任何key,叢集搭建相當順利!這個時候check已經成功了,ip順利的變成了重新配置的

127.0.0.1,現在嘗試對資料進行恢復具體步驟是將之前的轉移的備份檔案覆蓋新生成的備份檔案,然後重啟redis服務,

這裡使用aof來恢復資料





重啟之後乍一看是恢復成功了,但是check的時候發現了異常


且get資料也有問題


到這一步,我挖了個大坑....fix不成功之後我直接將1243和5798兩個槽設成了stable,check是成功了,但是get key根本

get不到資料,可以說資料被我玩壞了...第一次失敗了,不過反正之前的備份檔案還在,重頭再來吧...移除配置、重新搭建

叢集、覆蓋備份檔案、重啟服務,遇到了同樣的問題,果然還是原來的配方....不過這次學聰明瞭,經過一番研究,我找到

了某個博主的fix經驗,原來之前每次使用fix都失敗是這樣的原因!!這裡引用下這位博主的總結經驗。

fix的作業流程:

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修復異常slot,須要明確告訴redisslot的目標節點是哪個,源節點是哪個,而我之前的一系列操作造成了

兩個問題slot只存在目標節點,把源節點丟失了(因為check的時候發現只有importing狀態,而沒有migrating狀態),那fix當然

不成功啊!

修改如下:



為這兩個問題節點指定源節點,重新fix,成功,且資料恢復正常。最後對比下第一次fix失敗列印的日誌和fix成功

列印的日誌。

失敗日誌:


成功日誌:


總結:

1.搭建redis叢集,伺服器的ip必須要設定成固定

2.對問題slot,不要輕易設定stable,很容易造成資料丟失

3.後面的叢集測試發現即使migrating和imorting狀態都存在,依然可能fix失敗(不得不吐槽,redis-cluster的坑有很多啊)

此時可以使用CLUSTER SETSLOT <slot> NODE <node_id>搭配CLUSTER BUMPEPOCH來強制叢集的其他節點同意slot

的歸屬。

叢集命令彙總

CLUSTER INFO 列印叢集的資訊

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

節點

CLUSTER MEET <ip> <port>  ip port所指定的節點新增到叢集當中,讓它成為叢集的一份子。

CLUSTER FORGET <node_id> 從叢集中移除 node_id指定的節點。

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

CLUSTER SAVECONFIG 將節點的配置檔案儲存到硬盤裡面。

(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)。

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

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

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