[技术]Redis数据迁移
redis 数据迁移至 twemproxy redis 集群
在之前的文章讲到实现redis集群高可用,可以查看链接:twemproxy + redis + sentinel 实现redis集群高可用
但是要从旧的redis中将数据迁移到redis集群确实还是要想想办法,因为集群的前端是 twemproxy .
反正想来想去,实在没有办法了,了解到了redis的这三个命令 dump 、 pttl 、restore
那就用最原始的方法,将redis的每个key的数据从旧redis直接dump出来,然后通过restore命令导入到 twemproxy redis 集群中。
先来了解一下redis的这三个命令 dump 、 pttl 、restore
Redis DUMP 命令
Redis DUMP 命令用于序列化给定 key ,并返回被序列化的值
命令基本语法:
redis 127.0.0.1:4500 > DUMP KEY_NAME
如果 key 不存在,那么返回 nil 。 否则,返回序列化之后的值
[root@localhost ~\]# redis-cli -h 192.168.1.101 -p 4503
192.168.1.101:4503> SET huangdc "hello,welcome huangdc.com!"
OK
192.168.1.101:4503> GET huangdc
"hello,welcome huangdc.com!"
192.168.1.101:4503>
192.168.1.101:4503> DUMP huangdc
"\\x00\\x1ahello,welcome huangdc.com!\\x06\\x00\\xfe\\xe1:\\xea\_)7\\xe0"
192.168.1.101:4503>
Redis PTTL 命令
Redis PTTL 命令以毫秒为单位返回 key 的剩余过期时间。
命令基本语法如下:
redis 127.0.0.1:6379> PTTL KEY_NAME
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以毫秒为单位,返回 key 的剩余生存时间。
注意:在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
192.168.1.101:4503> GET huangdc
"hello,welcome huangdc.com!"
192.168.1.101:4503> PTTL huangdc
(integer) -1
192.168.1.101:4503>
192.168.1.101:4503> PEXPIRE huangdc 204800
(integer) 1
192.168.1.101:4503>
192.168.1.101:4503> PTTL huangdc
(integer) 201868
192.168.1.101:4503>
Redis RESTORE 命令
反序列化给定的序列化值,并将它和给定的 key 关联
命令基本语法:
redis 127.0.0.1:6379> RESTORE KEY_NAME ttl serialized-value [REPLACE]
参数 ttl 以毫秒为单位为 key 设置生存时间;如果 ttl 为 0 ,那么不设置生存时间。(ttl 的值需要通过 PTTL 命令来回去)
RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查,如果 RDB 版本不相同或者数据不完整的话,那么 RESTORE 会拒绝进行反序列化,并返回一个错误。
如果键 key 已经存在, 并且给定了 REPLACE 选项, 那么使用反序列化得出的值来代替键 key 原有的值;
相反地, 如果键 key 已经存在, 但是没有给定 REPLACE 选项, 那么命令返回一个错误。
192.168.1.101:4503>
192.168.1.101:4503> GET huangdc
"hello,welcome huangdc.com!"
192.168.1.101:4503> DUMP huangdc
"\\x00\\x1ahello,welcome huangdc.com!\\x06\\x00\\xfe\\xe1:\\xea\_)7\\xe0"
192.168.1.101:4503> PEXPIRE huangdc 2048000
(integer) 1
192.168.1.101:4503> PTTL huangdc
(integer) 1971895
192.168.1.101:4503> GET huangdc2
(nil)
192.168.1.101:4503> RESTORE huangdc2 1971895 "\\x00\\x1ahello,welcome huangdc.com!\\x06\\x00\\xfe\\xe1:\\xea\_)7\\xe0"
OK
192.168.1.101:4503> GET huangdc2
"hello,welcome huangdc.com!"
192.168.1.101:4503>
好了,大家知道了,就是将 dump 出来的序列化的值重新RESTORE 到新的key去即可 ,即完成了数据的导入导出
python多线程脚本实现迁移
最后,贡献一个多线程小脚本来实现:(python脚本,大家提前需要安装redis模块,pip install redis 即可安装)
# -\*- coding: utf-8 -\*-
"""
info: migrate redis cache (redist to twemproxy)
date: 2016-05-12
author: DcHuang
"""
import redis
import os
import sys
import time
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool
def usage():
print "Usage: %s src\['1.1.1.1:4500'\] dst\['2.2.2.2:14500'\]" % sys.argv\[0\]
try:
src=str(sys.argv\[1\])
dst=str(sys.argv\[2\])
src\_ip = src.split(':')\[0\]
src\_port = src.split(':')\[1\]
dst\_ip = dst.split(':')\[0\]
dst\_port = dst.split(':')\[1\]
except Exception,e:
usage()
sys.exit()
now\_time = int(time.time())
"""connect redis"""
try:
src\_pool = redis.ConnectionPool(host=str(src\_ip), port=int(src\_port))
src\_redis = redis.Redis(connection\_pool=src\_pool)
except:
print "src redis %s connection fail" % src
sys.exit()
try:
dst\_pool = redis.ConnectionPool(host=str(dst\_ip), port=int(dst\_port))
dst\_redis = redis.Redis(connection\_pool=dst\_pool)
except:
print "dst redis %s connection fail" % dst
sys.exit()
"""导入导出"""
def dump\_restore(key):
"""获取pttl"""
s\_pttl = src\_redis.pttl(key)
if s\_pttl == -2 :
return "1"
elif s\_pttl == -1 :
s\_pttl = 0
else:
s\_pttl = 0
"""获取key的dump,并且restore 导入到新的redis中"""
try:
s\_dump = src\_redis.dump(key)
if s\_dump:
d\_status = dst\_redis.restore(key,int(s\_pttl),s\_dump)
#print "key:",str(key)," type:",str(src\_redis.type(key))," pttl:",str(s\_pttl) ##," d\_status:",str(d\_status)
except:
return "1"
return "0"
"""创建线程执行导出导入函数"""
pool = ThreadPool(10)
results = pool.map(dump\_restore,src\_keys\_all)
pool.close()
pool.join()
new\_time = int(time.time())
################
print "use time(s):",str(new\_time - now\_time)