一、介绍

redis-port是一款redis数据迁移工具,用来将数据从一个redis迁移到另一个redis实例/redis集群中 ,以下是官方地址:

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

使用也是非常的简单:

/redis-port sync -f 127.0.0.1:6379 -t 127.0.0.1:6380 -n 8

上述命令将127.0.0.1:6379这个redis实例的数据迁移到 127.0.0.1:6380 中。

我们在生产上迁移了多个redis集群的数据,运行非常稳定。

最近有这么一个场景:只迁移指定前缀的key,因为一个redis集群有好几个应用在用,如果全部都迁,时间太长,占的内存也比较大。

二、改造过程

我们先整理下redis-port的工作流程:

1、伪装一个从,向主redis 发起同步请求;

2、主redis将当前数据以rdb发送给redis-port;

3、redis-port解析rdb文件,然后1条1条的向目标redis写入数据;

4、接收主redis发送过来的增量命令,发往目标redis。

所以如果要改造的话,需要修改3和4两处,当然了还得增加参数解析的代码,具体步骤如下:

1、先修改cmd/flags.go 增加前缀的参数:

type Flags struct {
Source, Target string //过滤前缀,即只迁移这个前缀的key
SourcePrefixs []string AofPath string
TmpFile struct {
Path string
Size int64
}
ExpireOffset time.Duration
}

  

其中SourcePrefixs为新加的字段,类型为一个字符串数组,因为前缀可能有多个。

2、修改cmd/flags.go解析参数函数parseFlagsFromArgs

  for _, key := range []string{"--sourcePrefix"} {
var prefix string
if s, ok := d[key].(string); ok && s != "" {
prefix = s
} //通过,分隔
flags.SourcePrefixs = strings.Split(prefix, ",")
}

3、修改cmd/libs.go,增加判断key是否包含指定前缀的函数

func strHasPrefix(key string, sourcePrefix []string)  bool{
if len(sourcePrefix) < 1 {
return true
} var hasPrefix bool
hasPrefix = false
for i := 0; i < len(sourcePrefix); i++{
if (strings.HasPrefix(key, sourcePrefix[i])) {
hasPrefix = true
break
}
} return hasPrefix
}

  

4、修改cmd/libs.go处理rdb文件的函数genRestoreCommands增加相应逻辑

//过滤非前缀的key
if (strHasPrefix(e.Key.String(), sourcePrefix) != true) {
log.Debug(e.Key.String() + " has no prefix: ignore it")
return
}

doRestoreDBEntry增加sourcePrefix参数

func doRestoreDBEntry(entryChan <-chan *rdb.DBEntry
, targetPrefix string, sourcePrefix []string, addr, auth string, on func(e *rdb.DBEntry) bool) {

5、修改cmd/libs.go回放aof文件函数doRestoreAoflog

func doRestoreAoflog(reader *bufio2.Reader, targetPrefix string, sourcePrefix []string, addr, auth string, on func(db uint64, cmd string) bool) {

//省略一些代码

//如果前缀不为空,则判断是否为这个前缀
if (len(r.Array) > 1) {
var key= string(r.Array[1].Value)
if strHasPrefix(key, sourcePrefix) != true {
continue
}
} //后续逻辑处理
}

6、在入口cmd/sync.go增加参数声明

Options:
-n N, --ncpu=N Set runtime.GOMAXPROCS to N.
-m MASTER, --master=MASTER The master redis instance ([auth@]host:port).
-t TARGET, --target=TARGET The target redis instance ([auth@]host:port).
--sourcePrefix=SP filter source key use prefix, separte with, .
--db=DB Accept db = DB, default is *.
--tmpfile=FILE Use FILE to as socket buffer.

再make编译下,可以试下效果:

开两个redis实例,实例A为6379端口,实例B为6380端口,实例A数据如下:

执行redis-sync:

可以看到只有order前缀的数据才迁移过来了。

Redis迁移工具redis-port使用&代码分析

扩展Redis:增加Redis命令

更多精彩文章,请关注公众号:

redis-port支持前缀迁移的更多相关文章

  1. 用redis实现支持优先级的消息队列

    http://www.cnblogs.com/tianqiq/p/4309791.html http://www.cnblogs.com/it-cen/p/4312098.html http://ww ...

  2. Redis删除相同前缀的key

          如何优雅地删除Redis set集合中前缀相同的key?       Redis中有删除单条数据的命令DEL,却没有批量删除特定前缀key的指令,但我们经常遇到需要根据前缀来删除的业务场景 ...

  3. Redis01——Redis究竟支持哪些数据结构

    Redis已经越来越多地应用到互联网技术中,而关于Redis的相关问题,也成为面试中必不可少的一部分,本文开始将会逐渐把我了解到的关于Redis的一些面试问题整理出来,供各位参考,如有不对之处,烦请指 ...

  4. php redis 获取指定前缀的所有key

    php redis 获取指定前缀的所有key 以laravel框架为例: $key = $this->redis->keys('db:shipping:shippingId:' . &qu ...

  5. Redisson使用起来很方便,但是需要redis环境支持eval命令

    Redisson使用起来很方便,但是需要redis环境支持eval命令,否则一切都是悲剧,比如me.结果还是要用RedisCommands去写一套.例子就如下,获得一个RLock锁对象,然后tryLo ...

  6. 从ASM迁移到ARM(1):平台支持的迁移服务

    Azure上的ARM模式为用户带来更好的管理,更多新的特性,更好的体验,因此目前正在使用经典模式(ASM)的用户,在了解和使用了ARM之后,也在考虑如何将原来基于ASM模式的虚拟机,存储,网络等IAA ...

  7. Redis所支持的数据结构

    1.启动Redis2.Redis所支持的数据结构 2.1.Redis常用操作 2.2.String类型及操作 2.3.Hash类型及操作 2.4.List类型及操作 2.5.Set类型及操作 2.6. ...

  8. Android 支持库迁移到AndroidX

    一.背景 Android系统版本在不断更新,从最初的Android 1.0到现在Google和各大手机厂商正在推的Android 10,平均下来每个年头都有一个大的版本更新.但用户正在用的手机上的An ...

  9. redis不支持多个数据库实例但是支持多个字典

    Redis多个数据库 注意:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念. Redis是一个字典结构的存储服务器,而实际上一个Redi ...

随机推荐

  1. 如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了

    一:背景 1. 讲故事 记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营 ...

  2. Linux三剑客老三---grep

    1.Linux三剑客老三 过滤需要的内容,例子:grep -v oldboy hello.txt grep一般常用参数: -a:在二进制文件中,以文本文件的方式搜索数据. -c:计算找到"搜 ...

  3. ASP.Net中的async+await异步编程

    在.NET Framework4.5框架.C#5.0语法中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP).在这种方式下,可以通过类似同步方式编写异步代码,极大简 ...

  4. ubuntu apt 相关命令

    sudo apt-get update  更新源sudo apt-get install package 安装包sudo apt-get remove package 删除包sudo apt-cach ...

  5. 你所不知道的Spring的@Autowired实现细节

    前言 相信很多Java开发都遇到过一个面试题:Resource和Autowired的区别是什么?这个问题的答案相信基本都清楚,但是这两者在Spring中是如何实现的呢?这就要分析Spring源码才能知 ...

  6. Java多线程_Master-Worker设计模式

    Master-Worker模式是常用的并行模式之一,它的核心思想是:系统由Master进程和Worker进程两类进程协同工作,Master负责接收和分配任务,Wroker负责处理子任务.当各个Work ...

  7. 高并发&性能优化(一)------总体介绍

    [开篇词] 本文主要通过一些经典的高并发场景,以及一些基本的运维工具来讲述一些关于高并发以及性能优化相关的内容,主要包括性能瓶颈的定位,性能调优的思路和技巧等. [性能的衡量指标] ?什么是性能 性能 ...

  8. 拿捏了!ConcurrentHashMap!

    概述 本文将对JDK8中 ConcurrentHashMap 源码进行一定程度的解读.解读主要分为六个部分:主要属性与相关内部类介绍.构造函数.put过程.扩容过程.size过程.get过程.与JDK ...

  9. 浅析一个lua文件窥slua工作机制

    slua的东西不是几句话能讲得完,这里只说结论不说原因,原因有空写个Little Slua工程来解释,下面注释中有几个关键点:LuaVar系列类:LuaFunction,LuaTable,LuaDel ...

  10. photonServer学习之连接数据库

    string connectStr = "server=127.0.0.1;port=3306;database=database;user=root;pwd=root";//连接 ...