Redis开发与运维:数据迁移(redis数据迁移指定的db)
mhr18 2024-11-15 22:12 18 浏览 0 评论
问题
最近项目重构,提前想把一台上的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 不是原子操作
补充同步工具:
https://github.com/CodisLabs/redis-port
其实一开始的策略就是使用同步工具,但是考虑到实在不知所以然,就看了直接的redis同步。简单的命令就能解决问题。
但是同步工具应该会有更多的应用场景和覆盖面积。
redis-port parse redis rdb file, sync data between redis master and slave --主从同步工具
工具简单,命令也不复杂。
上一篇,有朋友留言redis-port,借此机会我尝试使用一下redis-port这个同步工具
redis-port 已编译版
https://github.com/CodisLabs/redis-port/releases
cd 到解压目录
redis-dump
定义:持久化数据
执行:$ ./redis-dump 127.0.0.1:6999 -o dd/dump.rdb
验证
$ ls -ls
总用量 4
4 -rw-r--r-- 1 sunchong sunchong 217 10月 21 17:36 dump.rdb
redis-decode
定义:dumped payload to human readable format (hex-encoding)【反序列化rdb,更加容易理解】
Help:$ ./redis-decode --help
Usage:
redis-decode [--ncpu=N] [--input=INPUT|INPUT] [--output=OUTPUT]
redis-decode --version
Options:
-n N, --ncpu=N Set runtime.GOMAXPROCS to N.
-i INPUT, --input=INPUT Set input rdb encoded file. [default: /dev/stdin].
-o OUTPUT, --output=OUTPUT Set output file. [default: /dev/stdout].
Examples:
$ redis-decode -i dump.rdb -o dump.log
$ redis-decode dump.rdb -o dump.log
$ cat dump.rdb | redis-decode --ncpu=8 > dump.log
执行:$ ./redis-decode -i dump.rdb -o stdout
2019/10/21 15:42:40 decode.go:59: [INFO] decode: input = "dump.rdb", output = "stdout"
2019/10/21 15:42:40 decode.go:110: [INFO] decode: (r,w,o) = (read,write,objects)
2019/10/21 15:42:40 decode.go:135: [INFO] decode: file = 134 - [100.00%] (r,w,o)=(134,114,2) ~ (134,114,-)
2019/10/21 15:42:40 decode.go:139: [INFO] decode: done
验证:$ vim stdout
{"db":0,"type":"list","key":"right","index":0,"value":"r1"}
{"db":0,"type":"string","key":"QBT","value":"value1"}
redis-restore
从 6999 db0 dump.rdb 持久化到 7999 db0
from 127.0.0.1:6999 to 127.0.0.1:7999
执行:$ ./redis-restore -i dump.rdb -t 127.0.0.1:7999
2019/10/21 17:05:39 restore.go:70: [INFO] restore: input = "dump.rdb", aoflog = "" target = "127.0.0.1:7999"
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)
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,-,-)
2019/10/21 17:05:39 restore.go:159: [INFO] restore: done
验证:$ ./redis-restore -i dump.rdb -t 127.0.0.1:7999
127.0.0.1:7999> KEYS *
1) "right"
2) "QBT"
redis-sync
定义:实例间实时同步
执行:$ ./redis-sync 127.0.0.1:6999 -t 127.0.0.1:7999
验证
2019/10/21 17:41:16 sync.go:76: [INFO] sync: master = "127.0.0.1:6999", target = "127.0.0.1:7999"
2019/10/21 17:41:16 sync.go:109: [INFO] sync: runid = "42d23b2a5d2a4fcce612854174bfc6db89d52cca", offset = 0
2019/10/21 17:41:16 sync.go:111: [INFO] sync: rdb file = 217 (217)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
127.0.0.1:6999> SET sc sc1
OK
127.0.0.1:6999> SET sc sc2
OK
127.0.0.1:6999> SET sc sc3
OK
127.0.0.1:6999> SET sc sc4
OK
127.0.0.1:6999> SET sc sc5
OK
127.0.0.1:6999>
目标:127.0.0.1:7999
127.0.0.1:7999> get sc
"sc5"
127.0.0.1:7999>
总结
工具对应的是 redis 4.X版本
只是尝试了一下linux,windows下还没尝试,后续如有场景可以补充
相关推荐
- C++开发必知的内存问题及常用的解决方法-经典文章
-
1.内存管理功能问题由于C++语言对内存有主动控制权,内存使用灵活和效率高,但代价是不小心使用就会导致以下内存错误:omemoryoverrun:写内存越界odoublefree:同一块内...
- 缓存用不好,系统崩得早!10条军规让你成为缓存高手
-
凌晨三点,我被电话惊醒:“苏工!首页崩了!”监控显示:缓存命中率0%,数据库QPS10万+,线程阻塞2000+。根本原因竟是同事没加缓存!不会用缓存的程序员,就像不会刹车的赛车手——...
- 彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏
-
作为C/C++开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C++语言的特性引起的。C/C++语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成...
- Java中间件-Memcached(Java中间件大全)
-
一、知识结构及面试题目分析缓存技术的大规模使用是互联网架构区别于传统IT技术最大的地方,是整体高并发高性能架构设计中是重中之重的关键一笔,也是互联网公司比较偏好的面试题目。按照在软件系统中所处位置...
- linux内存碎片防治技术(linux内存碎片整理)
-
推荐视频:90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc原理剖析Linux内核内存分配与回收Linuxkernel组织管理物理内存的方式是buddysystem(伙...
- Redis主从架构详解(redis主从配置详细过程)
-
Redis主从架构搭建Redis主节点配置创建主节点目录(/opt/redis-master),复制redis.conf到该目录下,redis.conf配置项修改#后台启动daemonizeyes...
- 揭开CXL内存的神秘面纱(内存c1)
-
摘要:现代数据中心对内存容量的高需求促进了内存扩展和分解方面的多条创新线,其中一项获得极大关注的工作是基于ComputeeXpressLink(CXL)的内存扩展。为了更好地利用CXL,研究人员建...
- 一文彻底弄懂 TPS RPS QPS(tps cps)
-
以下是关于RPS、QPS、TPS的核心区别与关联的总结,结合实际场景和优化建议:一、核心定义与区别RPS:RequestsPerSecond每秒请求数客户端到服务器的完整请求数量Web服务...
- 用Redis的“集合”找出你和朋友的“共同关注”
-
你是不是在刷抖音、微博、小红书的时候,常常会看到这样的提示:“你和XXX有共同关注的博主/朋友”?或者当你关注了一个新的明星,系统会推荐“你的朋友YYY也关注了这位明星”?这个看似简单的功能背后,其实...
- WOT2016彭哲夫:科班出身开发者对运维人员的期许
-
“运维与开发”是老生常谈的话题,前几天和一个运维人聊天,TA说一些公司运维岗位都不公开招聘了,这让众多运维人员情何以堪?是运维的岗位真的饱和了?是找到合适的运维人才难?还是有这样那样的因素?带着这些疑...
- Java程序员最常用的20%技术总结(java程序员要掌握什么)
-
我听说编程语言,经常使用的是其中20%的技术。在Java这门语言中,这20%包括哪些内容?找到一份Java初级程序员的工作,有哪些是必须掌握的,有哪些是可以现学现卖的?一个完整的Javaweb项目,有...
- 秒杀系统实战(四)| 缓存与数据库双写一致性实战
-
前言微笑挖坑,努力填坑。————已经拥有黑眼圈,但还没学会小猪老师时间管理学的蛮三刀同学本文是秒杀系统的第四篇,我们来讨论秒杀系统中「缓存热点数据」的问题,进一步延伸到数据库和缓存的...
- 头条评论精灵翻牌子(头条评论精灵翻牌子怎么弄)
-
关于“头条评论精灵翻牌子”功能,这通常是指平台通过算法或运营手段,将用户的优质评论随机或定向推送到更显眼的位置(如信息流顶部、独立曝光位等),以提升互动率和用户参与感。以下是详细解析和建议:一、功能理...
- 15个程序员们都应该知道的大模型高级提示词指令模板和示例
-
作为程序员你如何写大模型指令?你写的指令是不是更专业呢?下面是15个程序员使用的专业的大模型指令,如果早知道可以能节省你很多时间。这些指令可以用在chatgpt,deepseek等大模型。1.一键...
- MyBatis-Plus内置的主键生成策略有大坑,要注意!
-
昨天小伙伴使用Mybaits-Plus开发的项目线上(集群、K8S)出现了主键重复问题,其报错如下:Mybatis-Plus启动时会通过com.baomidou.mybatisplus.core.to...
你 发表评论:
欢迎- 一周热门
-
-
Redis客户端 Jedis 与 Lettuce
-
高并发架构系列:Redis并发竞争key的解决方案详解
-
redis如何防止并发(redis如何防止高并发)
-
开源推荐:如何实现的一个高性能 Redis 服务器
-
redis安装与调优部署文档(WinServer)
-
Redis 入门 - 安装最全讲解(Windows、Linux、Docker)
-
一文带你了解 Redis 的发布与订阅的底层原理
-
Redis如何应对并发访问(redis控制并发量)
-
oracle数据库查询Sql语句是否使用索引及常见的索引失效的情况
-
Java SE Development Kit 8u441下载地址【windows版本】
-
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)