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 不是原子操作