Redis现在是互联网公司缓存的标配了,在一些场景下我们需要将redis的数据从一些实例迁移到其它实例上,一个好的Redis数据迁移工具可以起到事半功倍的效果,今天为大家介绍一款好用、稳定的工具:redis-port,我们在生产环境上有实际使用过。
源码地址:https://github.com/CodisLabs/redis-port
1、安装
先安装go,然后进入源代码的根目录,直接make就可以了;
我用的分支是redis-4.x-cgo。
2、使用
主要讲下迁移数据吧,redis-port有很多参数,这里只列一些常用参数:
-m:表示从哪里迁
-t:表示迁移到哪里去
./bin/redis-sync -m 172.21.106.228:6379 -t 172.21.106.228:9001
表示将数据从 172.21.106.228:6379 迁移到 172.21.106.228:9001
3、工作原理
讲工作原理之前,先了解下redis主、从同步的原理,因为redis-port的工作原理就是把自己模拟成一个从,利用主、从同步机制来完成数据迁移的。
在2.8之前redis主、从同步只有一种方式:sync
(图片来自 https://blog.csdn.net/sk199048/article/details/50725369 )
从服务器向主服务器发送sync命令,主服务器收到命令后,在后台用BGSAVE生成快照,然后将快照发送给从服务器。
另外主服务器生成RDB快照之后,将这个之后的写命令保存在一个缓冲区中,从服务器回放完命令后,主服务器将缓冲区的命令发送给从服务器。
这种方式在以下几个场景会有大的问题:
1、由于网络抖动从服务器暂时连不上主服务器,过了几秒后网络恢复了,这个期间其实只有很少的写操作,但也得全量同步,数据量比较小还好,如果量达到几十G了,这个时候主服务器基本上挂了;
2、一些从服务器因为升级、硬件等原因,需要暂时重启下,也得全量同步 ;
PSYNC1
sync的方式每次都全量同步,那能不能增量同步呢,PSYNC1就是为了解决这个问题而诞生的。
它的原理如下:
主服务器在运行时记录自己的运行ID,从服务器也会记录主服务器ID,如果因为网络抖动导致的主、从暂时断开,下次重连时,从服务器把主服务器 ID和偏移量等信息发送给主服务器,主服务器检查运行ID是否和自己相同,然后检查偏移量是否在复制缓冲区中,只要时间不断开太久,复制缓存冲不是太小,就可以进行增量同步了。
(PSYNC1只解决上面场景1的问题,Redis4.0推出的PSYNC2可以解决场景2下的问题)
再回到redis-port上,我们看下它的工作原理,先统一几个概念:
源服务器:表示要从哪个redis实例迁移数据
目标服务器:表示将数据迁到哪个实例上
工作原理如下:
1)、redis-port向源服务器发送PSYNC命令;
2)、源服务器将当前快照发送给redis-port;
3)、redis-port解析快照命令,发送给目标服务器;
4)、源服务器不断的将复制缓冲区的内容发送给Redis-port;
5)、redis-port将收到的复制缓区内容发送给目标服务器;
4、关键代码分析
发送psync命令
代码语言:javascript复制var runid, offset, rdbSizeChan = redisSendPsyncFullsync(master.rd, master.wt)
解析RDB,发送给目标服务器;然后解析增量AOF日志:
代码语言:javascript复制var jobs = NewParallelJob(flags.Parallel, func() {
doRestoreDBEntry(entryChan, target.Addr, target.Auth,
func(e *rdb.DBEntry) bool {
if !acceptDB(e.DB) {
master.rdb.skip.Incr()
return false
}
master.rdb.forward.Incr()
return true
})
}).Then(func() {
//解析主服务器发送过来的Aof日志
AofdoRestoreAoflog(reader, target.Addr, target.Auth,
func(db uint64, cmd string) bool {
if !acceptDB(db) && cmd != "PING" {
master.aof.skip.Incr()
return false
}
master.aof.forward.Incr()
return true
})
}).Run()
如果有自定义需求,就可以从上面2处入手。
5、写在最后
使用redis-port迁移数据需要停机吗,答案是需要,因为在迁移数据的时候源服务器会不断的有写请求进来,等真正迁移完的时候停服才能保证数据一致,准备工作做的好的话,这个过程会很短。