Redis開發與運維:數據遷移

  • 2019 年 10 月 11 日
  • 筆記

問題

最近項目重構,提前想把一台上的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  "x00x0b0x001,1,2,3x06x00xfbx06ZUnxdexb5x95"  

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

127.0.0.1:7999[2]> RESTORE QianBiTou:VC:Config 0 "x00x0b0x001,1,2,3x06x00xfbx06ZUnxdexb5x95"  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 不是原子操作

Tags: