问题

最近项目重构,提前想把一台上的redis实例转移到另一台redis实例上。

  1. redis数据库:阿里云RedisVPC网络、Server版本2.8.19
  2. 目标数据库:阿里云RedisVPC网络、Server版本4.0.11

前提:

  1. 当前我们使用Redis作为我们的数据库(永久+ 临时缓存)

目标:

  1. 把当前永久性数据导入到目标数据库,临时缓存数据不做处理

方案

  1. 设置主从复制,这个应该是比较稳妥的方案,但是支持主从必须3.0以上 -- 这个方案否掉了
  2. 那就使用键迁移命令,查了一下三种方式:move dump + restore migrate

自测

  1. Windows服务器,下载了源数据库 redis2.8.19
  2. 分别启用了两个实例分别是 69997999
  3. 源数据 6999,目标数据 7999

move

这个命令是做实例内,db迁移的,对于当前实例间同步是不满足的。

但也不妨尝试一下:

db5中的键移到db6,

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

移动嘛所以db5的键就没了,db6才能获取到

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

dump + restore

1、源数据库上:dump 相当于把这个键按照协议序列化

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

2、目标数据库上:restore 进行初始化这个键

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

这个方案呢,可行但是看了一下第三个,感觉第3个是2的改进版本

migrate

  1. localhost:6999[6]> help migrate
  2. MIGRATE host port key destination-db timeout [COPY] [REPLACE]
  3. summary: Atomically transfer a key from a Redis instance to another one.
  4. since: 2.6.0
  5. group: generic

从这到那:127.0.0.1:6999 -> 127.0.0.1:7999 key=QianBiTou:VC:Config

1、看看源数据库6999,db6这个key的值。嗯,有值。

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

2.、再看看目标数据库,把这个key清场.

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

3.、准备好了,那就开始转吧,走你

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

4、看看目标机器上过来了木有

  1. en, 过来了
  1. 127.0.0.1:7999[2]> GET QianBiTou:VC:Config
  2. "0x001,1,2,3"

5.、再看看源数据库

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

再进一步

  1. 查阅资料发现,MIGRATE = dump + restore + del ,因为它是原子性的所以推荐使用这个方法。
  2. 但是会把原来的数据删掉,类似于跨实例move。文档中 加上copyreplace 参数就不会删除源数据了。
  • copy 复制

  • replcae 复制并替换

1.、再试试,数据重新加回去

  1. localhost:6999[6]> set QianBiTou:VC:Config 0x001,1,2,3
  2. OK
  3. localhost:6999[6]> MIGRATE 127.0.0.1 7999 QianBiTou:VC:Config 2 5000 replace
  4. (error) ERR wrong number of arguments for 'migrate' command

2.、报错了,再查查官方资料。好吧,还是版本不支持:

  1. 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 这个算是最终方案

  1. 方案可行性:因为不涉及缓存数据,是永久数据的导出导入,所以不存在原子性问题,还有忘记了一点数据量非常小

执行方案

  1. [TestMethod]
  2. public async Task RestoreToOtherRedis_Test()
  3. {
  4. // 源redis
  5. string sourceRedis = "r-xxxxxxxxxxxpd.redis.rds.aliyuncs.com:6379,password=uuuuuu,defaultDatabase=5,prefix=";
  6. //目标redis
  7. string targetRedis = "r-xxxxxxxxxxxxpd.redis.rds.aliyuncs.com:6379,password=uuuuuu,defaultDatabase=5,prefix=";
  8. List<string> keys = new List<string>();
  9. try
  10. {
  11. using (var sourceClient = new CSRedis.CSRedisClient(sourceRedis))
  12. {
  13. // key 很少的时候使用cmd: keys *
  14. // 建议使用 scan
  15. keys = sourceClient.Keys("*").ToList();
  16. using (var targetClient = new CSRedis.CSRedisClient(targetRedis))
  17. {
  18. foreach (var key in keys)
  19. {
  20. if (key.StartsWith("RedisCach"))
  21. continue;
  22. // 序列化数据
  23. var dump = sourceClient.Dump(key);
  24. // 初始化数据
  25. var ok = targetClient.Restore(key, dump);
  26. }
  27. }
  28. }
  29. }
  30. catch (Exception ex)
  31. {
  32. string msg = ex.ToString();
  33. }
  34. finally
  35. {
  36. }

验证

  1. 事后验证了一下,确实数据过来了

注意点

  1. MOVE 实例内
  2. MIGRATE 原子操作。最好使用copyreplace 参数源数据不删除。
  3. DUMP + RESTORE 不是原子操作

补充同步工具:

https://github.com/CodisLabs/redis-port

其实一开始的策略就是使用同步工具,但是考虑到实在不知所以然,就看了直接的redis同步。简单的命令就能解决问题。

但是同步工具应该会有更多的应用场景和覆盖面积。

  1. redis-port parse redis rdb file, sync data between redis master and slave --主从同步工具

工具简单,命令也不复杂。

上一篇,有朋友留言redis-port,借此机会我尝试使用一下redis-port这个同步工具

redis-port 已编译版

  1. https://github.com/CodisLabs/redis-port/releases

cd 到解压目录

redis-dump

  1. 定义:持久化数据

执行:$ ./redis-dump 127.0.0.1:6999 -o dd/dump.rdb

验证

  1. $ ls -ls
  2. 总用量 4
  3. 4 -rw-r--r-- 1 sunchong sunchong 217 10 21 17:36 dump.rdb

redis-decode

  1. 定义:dumped payload to human readable format (hex-encoding)【反序列化rdb,更加容易理解】

Help:$ ./redis-decode --help


  1. Usage:
  2. redis-decode [--ncpu=N] [--input=INPUT|INPUT] [--output=OUTPUT]
  3. redis-decode --version
  4. Options:
  5. -n N, --ncpu=N Set runtime.GOMAXPROCS to N.
  6. -i INPUT, --input=INPUT Set input rdb encoded file. [default: /dev/stdin].
  7. -o OUTPUT, --output=OUTPUT Set output file. [default: /dev/stdout].
  8. Examples:
  9. $ redis-decode -i dump.rdb -o dump.log
  10. $ redis-decode dump.rdb -o dump.log
  11. $ cat dump.rdb | redis-decode --ncpu=8 > dump.log

执行:$ ./redis-decode -i dump.rdb -o stdout

  1. 2019/10/21 15:42:40 decode.go:59: [INFO] decode: input = "dump.rdb", output = "stdout"
  2. 2019/10/21 15:42:40 decode.go:110: [INFO] decode: (r,w,o) = (read,write,objects)
  3. 2019/10/21 15:42:40 decode.go:135: [INFO] decode: file = 134 - [100.00%] (r,w,o)=(134,114,2) ~ (134,114,-)
  4. 2019/10/21 15:42:40 decode.go:139: [INFO] decode: done

验证:$ vim stdout

  1. {"db":0,"type":"list","key":"right","index":0,"value":"r1"}
  2. {"db":0,"type":"string","key":"QBT","value":"value1"}

redis-restore

  1. 6999 db0 dump.rdb 持久化到 7999 db0
  2. from 127.0.0.1:6999 to 127.0.0.1:7999

执行:$ ./redis-restore -i dump.rdb -t 127.0.0.1:7999

  1. 2019/10/21 17:05:39 restore.go:70: [INFO] restore: input = "dump.rdb", aoflog = "" target = "127.0.0.1:7999"
  2. 2019/10/21 17:05:39 restore.go:126: [INFO] restore: (r,f,s/a,f,s) = (rdb,rdb.forward,rdb.skip/aof,rdb.forward,rdb.skip)
  3. 2019/10/21 17:05:39 restore.go:155: [INFO] restore: size = 134 - [100.00%, 0.00%] (r,f,s/a,f,s)=(134,0,2/0,0,0) ~ (134,-,-/0,-,-)
  4. 2019/10/21 17:05:39 restore.go:159: [INFO] restore: done

验证:$ ./redis-restore -i dump.rdb -t 127.0.0.1:7999

  1. 127.0.0.1:7999> KEYS *
  2. 1) "right"
  3. 2) "QBT"

redis-sync

  1. 定义:实例间实时同步

执行:$ ./redis-sync 127.0.0.1:6999 -t 127.0.0.1:7999

验证

  1. 2019/10/21 17:41:16 sync.go:76: [INFO] sync: master = "127.0.0.1:6999", target = "127.0.0.1:7999"
  2. 2019/10/21 17:41:16 sync.go:109: [INFO] sync: runid = "42d23b2a5d2a4fcce612854174bfc6db89d52cca", offset = 0
  3. 2019/10/21 17:41:16 sync.go:111: [INFO] sync: rdb file = 217 (217)
  4. 2019/10/21 17:41:16 sync.go:208: [INFO] sync: (r/f,s/f,s) = (read,rdb.forward,rdb.skip/rdb.forward,rdb.skip)
  5. 2019/10/21 17:41:17 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(217/2,0/0,0) ~ (217/-,-/-,-) ~ speed=(217/2,0/0,0)
  6. 2019/10/21 17:41:18 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(217/2,0/0,0) ~ (217/-,-/-,-) ~ speed=(0/0,0/0,0)
  7. 2019/10/21 17:41:19 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(217/2,0/0,0) ~ (217/-,-/-,-) ~ speed=(0/0,0/0,0)
  8. 2019/10/21 17:41:20 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(14/0,0/1,0)
  9. 2019/10/21 17:41:21 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  10. 2019/10/21 17:41:22 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  11. 2019/10/21 17:41:23 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  12. 2019/10/21 17:41:24 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  13. 2019/10/21 17:41:25 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  14. 2019/10/21 17:41:26 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  15. 2019/10/21 17:41:27 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  16. 2019/10/21 17:41:28 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  17. 2019/10/21 17:41:29 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(231/2,0/1,0) ~ (231/-,-/-,-) ~ speed=(0/0,0/0,0)
  18. 2019/10/21 17:41:30 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(245/2,0/2,0) ~ (245/-,-/-,-) ~ speed=(14/0,0/1,0)
  19. 2019/10/21 17:41:31 sync.go:250: [INFO] sync: rdb = 217 - [100.00%] (r/f,s/f,s)=(245/2,0/2,0) ~ (245/-,-/-,-) ~ speed=(0/0,0/0,0)

源:127.0.0.1:6999

  1. 127.0.0.1:6999> SET sc sc1
  2. OK
  3. 127.0.0.1:6999> SET sc sc2
  4. OK
  5. 127.0.0.1:6999> SET sc sc3
  6. OK
  7. 127.0.0.1:6999> SET sc sc4
  8. OK
  9. 127.0.0.1:6999> SET sc sc5
  10. OK
  11. 127.0.0.1:6999>

目标:127.0.0.1:7999

  1. 127.0.0.1:7999> get sc
  2. "sc5"
  3. 127.0.0.1:7999>
  1. 总结
  2. 工具对应的是 redis 4.X版本
  3. 只是尝试了一下linuxwindows下还没尝试,后续如有场景可以补充

Redis开发与运维:数据迁移的更多相关文章

  1. Redis开发与运维学习笔记

    <Redis开发与运维>读书笔记   一.初始Redis 1.Redis特性与优点 速度快.redis所有数据都存放于内存:是用C语言实现,更加贴近硬件:使用了单线程架构,避免了多线程竞争 ...

  2. Redis开发与运维:SDS

    STRING 我们会经常打交道的string类型,在redis中拥有广泛的使用.也是开启redis数据类型的基础. 在我最最开始接触的redis的时候,总是以为字符串类型就是值的类型是字符串. 比如: ...

  3. Redis 开发与运维

    Getting Start 高性能 性能优势的体现 C语言实现的内存管理 epoll的I/O多路复用技术+IO连接/关闭/读写通过事件实现异步的非阻塞IO TCP协议 单线程架构,不会因为高并发对服务 ...

  4. Redis实战(七)Redis开发与运维

    Redis用途 1.缓存 Redis提供了键值过期时间设置, 并且也提供了灵活控制最大内存和内存溢出后的淘汰策略. 可以这么说, 一个合理的缓存设计能够为一个网站的稳定保驾护航. 2.排行榜系统 Re ...

  5. 《Redis开发与运维》读书笔记

    一.初始Redis 1.Redis特性与优点 速度快.redis所有数据都存放于内存:是用C语言实现,更加贴近硬件:使用了单线程架构,避免了多线程竞争问题 基于键值对的数据结构,支持的数据结构丰富.它 ...

  6. 《Redis开发与运维》快速笔记(一)

    1.前言&基本介绍 在原始的系统架构中,我们都由程序直接连接DB,随着业务的进一步开展,DB的压力越来越大,为了缓解DB的这一压力,我们引入了缓存,在程序连接DB中加入缓存层, 从而减轻数据库 ...

  7. 《Redis开发与运维》

    第1章 初识Redis 1. Redis介绍: Redis是一种基于键值对(key-value)的NoSQL数据库. 与很多键值对数据库不同的是,Redis中的值可以是由string(字符串).has ...

  8. Redis开发与运维:数据迁移(下)

    上一篇,有朋友留言redis-port,借此机会我尝试使用一下redis-port这个同步工具 redis-port 已编译版 https://github.com/CodisLabs/redis-p ...

  9. redis 开发与运维 学习心得1

    主要是命令相关 第一章 初识Redis 1.redis是基于键值对的NoSQL. 2.redis的值可以是 string, hash, list, set, zset, bitmaps, hyperl ...

随机推荐

  1. POJ-2104 K-th Number CDQ分治

    题目传送门 题意:给你一个序列,长度为n,m次询问,询问一段区间的第k大. 题解:CDQ分治,对整个值域进行分治.每次取一个mid, 计算出整个区间内mid <= 的数目,如果 num > ...

  2. SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)

    题意:给出n个点n-1条边的树,有两个操作,一个是查询节点l到r的边的最大值,然后指定边的更改权值. 题解:差不多是树链剖分的模版题,注意每个点表示的边是连向其父亲节点的边. #include < ...

  3. 数论---GCD(最大公约数)+LCM(最小公倍数)

    #include<bits/stdc++.h> #define ll long long using namespace std; /* ll gcd(ll a, ll b) {//非递归 ...

  4. 安卓APP开发简单实例 结对编程心得

    开始说起搞APP开发,自己和小伙伴的编程水平真的很低,无从下手,只有在网上找点案列,学习着怎样开发,结对编程还是面临着许多问题的,大家的水平有所差异和编程风格不同,我们用eclipse做了一个仿微信登 ...

  5. Cookie的临时存储和定时存储

    Cookie解决了不同请求的数据共享问题.是由服务器保存在客户端的小文本文件,包含了用户的信息,可以避免用户重复输入用户名和密码进行登录.浏览器请求Cookie,服务器响应时返回Cookie,浏览器存 ...

  6. 【教程】Bluestacks0.7.9.860以上版3分钟教你摇一摇

    Bluestacks 0.7.9.860 版或以上 , 打开文件夹Win 7 用户 : C:\ProgramData\Bluestacks\UserData\InputMapperWin XP 用户 ...

  7. Java开发者薪资最低?程序员只能干到30岁?国外真的没有996?Intellij真的比Eclipse受欢迎?

    Stack Overflow作为全球最大的程序设计领域的问答网站,每年都会出据一份开发者调查报告.近日,Stack Overflow公布了其第9次年度开发者调查报告(https://insights. ...

  8. 关于java属性字段命名

    最近项目定义vo的时候,boolean类型数据定义成isProperty类型的,导致系统间数据交互过程中报错. 网上爬了良久: JavaBean命名规范里面规定,对于primitive和自定义类类型的 ...

  9. python Fatal error in launcher

    1.之前电脑上只安装了一个python2.7时pip install virtualenv安装了virtualenv,后来又装了py3.6.最近想做断网环境下的虚拟环境快速移植发现查看virtuale ...

  10. jstl.jar下载地址

    下载地址: 链接:https://pan.baidu.com/s/15_B1QLelWOvTGdC7BoAp4A 密码:vmdr