1. 程式人生 > >Redis開發與運維:資料遷移

Redis開發與運維:資料遷移

問題

最近專案重構,提前想把一臺上的redis例項轉移到另一臺redis例項上。

源redis資料庫:阿里雲Redis、VPC網路、Server版本2.8.19

目標資料庫:阿里雲Redis、VPC網路、Server版本4.0.11

前提:

當前我們使用Redis作為我們的資料庫(永久+ 臨時快取)

目標:

把當前永久性資料匯入到目標資料庫,臨時快取資料不做處理

方案

設定主從複製,這個應該是比較穩妥的方案,但是支援主從必須3.0以上  -- 這個方案否掉了

那就使用鍵遷移命令,查了一下三種方式:move 、dump + restore 、migrate

自測

Windows伺服器,下載了源資料庫 redis2.8.19

分別啟用了兩個例項分別是 6999和7999

源資料 6999,目標資料 7999

move

這個命令是做例項內,db遷移的,對於當前例項間同步是不滿足的。

但也不妨嘗試一下:

db5中的鍵移到db6,

localhost:6999[5]> get QianBiTou:VC:Config
"0x001,1,2,3"
localhost:6999[5]> move  QianBiTou:VC:Config 6
(integer) 1
localhost:6999[5]> get QianBiTou:VC:Config
(nil)

移動嘛所以db5的鍵就沒了,db6才能獲取到

localhost:6999[5]> SELECT 6
OK
localhost:6999[6]> get QianBiTou:VC:Config
"0x001,1,2,3"

dump + restore

1、源資料庫上:dump 相當於把這個鍵按照協議序列化

localhost:6999[6]> get QianBiTou:VC:Config
"0x001,1,2,3"
localhost:6999[6]> DUMP  QianBiTou:VC:Config
"\x00\x0b0x001,1,2,3\x06\x00\xfb\x06ZUn\xde\xb5\x95"

2、目標資料庫上:restore 進行初始化這個鍵

127.0.0.1:7999[2]> RESTORE QianBiTou:VC:Config 0 "\x00\x0b0x001,1,2,3\x06\x00\xfb\x06ZUn\xde\xb5\x95"
OK
127.0.0.1:7999[2]> GET QianBiTou:VC:Config
"0x001,1,2,3"

這個方案呢,可行但是看了一下第三個,感覺第3個是2的改進版本

migrate

localhost:6999[6]> help migrate

  MIGRATE host port key destination-db timeout [COPY] [REPLACE]
  summary: Atomically transfer a key from a Redis instance to another one.
  since: 2.6.0
  group: generic

從這到那:127.0.0.1:6999 -> 127.0.0.1:7999 key=QianBiTou:VC:Config

1、看看源資料庫6999,db6這個key的值。嗯,有值。

localhost:6999[6]> get QianBiTou:VC:Config
"0x001,1,2,3"

2.、再看看目標資料庫,把這個key清場.

127.0.0.1:7999[2]> GET QianBiTou:VC:Config
"0x001,1,2,3"
127.0.0.1:7999[2]> DEL QianBiTou:VC:Config
(integer) 1
127.0.0.1:7999[2]> GET QianBiTou:VC:Config
(nil)

3.、準備好了,那就開始轉吧,走你

localhost:6999[6]> get QianBiTou:VC:Config
"0x001,1,2,3"
localhost:6999[6]>  MIGRATE 127.0.0.1 7999 QianBiTou:VC:Config 2 5000
OK

4、看看目標機器上過來了木有

en, 過來了
127.0.0.1:7999[2]> GET QianBiTou:VC:Config
"0x001,1,2,3"

5.、再看看源資料庫

e...沒啦?
localhost:6999[6]> get QianBiTou:VC:Config
(nil)

再進一步

查閱資料發現,MIGRATE  = dump + restore + del ,因為它是原子性的所以推薦使用這個方法。

但是會把原來的資料刪掉,類似於跨例項move。文件中 加上copy和replace 引數就不會刪除源資料了。
  • copy 複製

  • replcae 複製並替換

1.、再試試,資料重新加回去

localhost:6999[6]> set QianBiTou:VC:Config 0x001,1,2,3
OK

localhost:6999[6]>  MIGRATE 127.0.0.1 7999 QianBiTou:VC:Config 2 5000 replace
(error) ERR wrong number of arguments for 'migrate' command

2.、報錯了,再查查官方資料。好吧,還是版本不支援:

    COPY and REPLACE are available only in 3.0 and above. KEYS is available starting with Redis 3.0.6. AUTH is available starting with Redis 4.0.7.

最終方案

1、主從 --不行,版本低了

2、MOVE-- 不行,例項內,資料沒了

3、 MIGRATE --不行,例項間,版本不行+資料沒了

4、 dump + restore 這個算是最終方案

方案可行性:因為不涉及快取資料,是永久資料的匯出匯入,所以不存在原子性問題,還有忘記了一點資料量非常小

執行方案

       [TestMethod]
        public async Task RestoreToOtherRedis_Test()
        {
            // 源redis
            string sourceRedis = "r-xxxxxxxxxxxpd.redis.rds.aliyuncs.com:6379,password=uuuuuu,defaultDatabase=5,prefix=";

            //目標redis
            string targetRedis = "r-xxxxxxxxxxxxpd.redis.rds.aliyuncs.com:6379,password=uuuuuu,defaultDatabase=5,prefix=";

            List<string> keys = new List<string>();
            try
            {
                using (var sourceClient = new CSRedis.CSRedisClient(sourceRedis))
                {
                    // key 很少的時候使用cmd: keys *
                    // 建議使用 scan
                    keys = sourceClient.Keys("*").ToList();
                    using (var targetClient = new CSRedis.CSRedisClient(targetRedis))
                    {

                        foreach (var key in keys)
                        {
                            if (key.StartsWith("RedisCach"))
                                continue;

                            // 序列化資料
                            var dump = sourceClient.Dump(key);

                            // 初始化資料
                            var ok = targetClient.Restore(key, dump);

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = ex.ToString();
            }
            finally
            {                
            }

驗證

事後驗證了一下,確實資料過來了

注意點

MOVE 例項內

MIGRATE 原子操作。最好使用copy和replace 引數源資料不刪除。

DUMP  + RESTORE 不是原子操作