天天看點

redis誤同步恢複

redis主備同步非常友善,通過slaveof指令即可同步。上周應用切換了redis,想讓新的redis和舊的redis進行資料同步,結果把新redis中其他應用已經寫入的所有資料都删除了。。。這裡記錄下恢複方法。

首先先恢複redis的dump檔案。還好現在阿裡雲彈性計算叢集給每個鏡像每天都進行了備份,通過操作前一天的備份鏡像,快照制作當時的整個redis目錄複制了出來,作為恢複的基礎。

然後将恢複回來的檔案再複制一份備份,原先那份修改redis的配置檔案,修改啟動端口(我從預設的6379改成了6479),然後啟動舊的redis,成功将當時的dump檔案載入到新的redis執行個體中。

查詢到redis有migrate指令,能夠将key遷移到另外一個redis執行個體中(具體參考這裡)。通過bash指令,循環的将備份的執行個體所有key,都試圖通過migrate指令遷移到新的redis中。

遷移過程中,遷移成功的key,在舊的執行個體中會被删除,失敗的key,可以看見失敗原因都是key is busy。也就是說,要遷移的key在新的執行個體中已經存在了。

和使用方确定了所有已經存在的key,是hash類型的,都是要保留的資料。是以,通過一個簡單的shell腳本,讀取備份執行個體中hash類型key,并添加到新的redis中。bash腳本為:

[cce lang=”bash”]

#!/bin/bash

old_redis="./redis-cli -p 6479"

new_redis="./redis-cli"

keys=`$old_redis keys '*'`

for k in $keys

do

key_type=`$old_redis type $k`

if [ $key_type = "hash" ]; then

hash_keys=`$old_redis hkeys $k`

for hash_key in $hash_keys

hash_value=`$old_redis hget $k $hash_key`

$new_redis hset $k $hash_key $hash_value

echo "merge $k $hash_key to new redis"

done

#eval "$old_redis del $k"

fi

[/cce]

邏輯非常簡單,就是先通過keys指令擷取到所有遷移失敗的key,然後通過type指令擷取類型。如果是hash類型的key,周遊所有的hash key,然後讀取出一個key下所有的鍵值對,并通過hset指令放到新的redis執行個體中。最後将合并完成的key從備份執行個體中删除。這裡由于業務上隻需要合并hash類型的,其他容器類型(list, set等)也可以通過類似的方式做新老合并。

轉載自:https://coolex.info/blog/427.html