Redis迁移及redis-shake介绍
1. Redis迁移介绍
工作中有时会遇到需要把原Redis集群下线,迁移到另一个新的Redis集群的需求(如机房迁移,Redis上云等原因)。此时原Redis中的数据需要如何操作才可顺利迁移到一个新的Redis集群呢? 本节简单介绍相关方法及一些工具。
redis有主从架构及redis-cluster架构,架构不同,两者的迁移方法也是不相同的。
1.1 Redis主从迁移
若原来的redis集群为主从结构,则迁移工作是相当简单方便的。可使用slaveof迁移或aof/rdb迁移数据。
- slaveof : 利用slaveof制作新的从库,从而达到数据迁移的目的。
- aof迁移: 暂停写服务,把aof文件导出到新的redis机群中完成数据迁移。
1.1.1 slaveof同步数据
如下示例:将把原来redis_master 192.124.64.212:6379迁移到新redis_master 192.124.64.214:6380。
#旧 redis_master 192.124.64.212:6379 --> 新redis_master 192.124.64.214:6380
1.数据同步
$redis-cli -h redis_master_new 6380 slaveof redis_master_old 6379
$redis-cli -h 192.124.64.214 6380 slaveof 192.124.64.212 6379
2.修改新read-only配置为no.
修改新redis的read-only配置为no,新的redis可以写数据。否则会出错.
$redis-cli -h 192.124.64.214 -p 6380 -a pwd123 set foo bar
(error) READONLY You can't write against a read only slave
查看当前slave-read-only配置
$redis-cli -h 192.124.64.214 -p 6380 -a pwd123 config get slave-read-only
1) "slave-read-only"
2) "yes"
$redis-cli -h 192.124.64.214 6380 config set slave-read-only no
$redis-cli -h 192.124.64.214 6380 config get slave-read-only
3. 业务停止对原redis停写.
4. 业务变更redis配置,重启web服务
业务修改redis配置为新的redis地址,并重启web服务。
5. 检查新/旧redis链接情况
旧redis:
redis-cli -h 192.124.64.212 -p 6379 -a pwd123 info clients
connected_clients:1
redis-cli -h 192.124.64.212 -p 6379 -a pwd123 client list
redis-cli -h 192.124.64.212 -p 6379 -a pwd123 client list |awk -F'addr=' '{print $2}' | awk '{print $1}'|awk -F':' '{print $1}'|sort |uniq -c|sort -nr
1 192.124.64.214
新redis:
redis-cli -h 192.124.64.214 -p 6380 -a pwd123 info clients
redis-cli -h 192.124.64.214 -p 6380 -a pwd123 dbsize
6.断开同步
redis-cli -h 192.124.64.214 -p 6380 info |grep role
redis-cli -h 192.124.64.214 -p 6380 slaveof NO ONE
OK
redis-cli -h 192.124.64.214 -p 6380 info |grep role
role:master
7. 测试业务情况(略)
1.1.2 aof同步数据
若是原来的redis可以暂停写操作,则咱们用aof来同步数据也很方便。
#旧redis导出aof文件
$redis-cli -h old_instance_ip -p old_instance_port config set appendonly yes
$redis-cli -h old_instance_ip -p old_instance_port configconfig get appendonly
1) "appendonly"
2) "yes"
#aof文件导入到新的redis
$redis-cli -h new_redis_instance_ip -p 6379 -a password --pipe < appendonly.aof
#导入完成后,关闭原redis AOF
$redis-cli -h old_instance_ip -p old_instance_port config set appendonly no
slaveof及aof迁移对比:
- slaveof 会把目标redis库上当前的key全部清除,这点要注意。
- 当redis数据量较大时使用slaveof xxx,会给master带来较大的压力。最好业务低峰时间处理。
- aof迁移数据可以保留新redis上已存在的数据,这点不同于slaveof。
- aof不能实时同步,所以迁移期间的redis增量数据不能同步,故常需要把原来的redis停写操作。
1.2 Redis集群迁移
Redis-cluster介绍:
Redis-cluster是 redis 的一个分布式实现,cluster将数据存储到多个不同Redis实例中,解决了单机Redis容量有限的问题。并且Redis-cluster某个节点故障时,若此节点有可用的从库,则redis-cluster将可以继续处理请求,从而实现了redis的高可用。
Redis-cluster迁移:
Redis-Cluster是由多个redis实例组成的集群,无法直接使用slave of 命令把redis-cluster-B变成redis-cluster-A的从库。
redis-cluster迁移方法:
- 若是业务可以中断,可停止Cluster-A 写操作,把Redis rdb/aof文件传输到新的Cluster-B机群再重启服务。
- 使用某些redis数据迁移工具来迁移redis-cluster数据。
1.3 Redis迁移工具
常见redis迁移工具网址:
- redis-dump: redis-dump 是一个将redis数据导入/导出为json格式数据的小工具。
- redis-port : 最初是 codis 项目相关工具,支持实时同步 redis 数据到 codis/redis等中。
- redis-migrate-tool: 是唯品会开源的redis数据迁移工具,可用于异构redis集群间的数据在线迁移。
- redis-shake : 是阿里云的redis数据同步的工具。支持redis主从->redis-cluster,cluster-cluster等多种redis架构的数据同步。
redis-dump:
redis-dump可以方便的把一个redis实例的数据导出来(不是redis-cluster的数据)。redis-dump命令需要用到keys命令,若是rename此命令,则redis-dump将会出错。
#把192.124.64.212:6379 数据导到192.124.64.214:6380。
$redis-dump -u :pwd123@192.124.64.212:6379 | redis-load -u :pwd123@192.124.64.214:6380
#
$redis-dump -u :pwd123@192.124.64.212:6379
{"db":0,"key":"foo","ttl":-1,"type":"string","value":"bar","size":3}
#keys不可用将出错
$redis-dump -u :pwd123@192.124.64.212:6379>redis_6379.json
ERR unknown command 'keys'
redis-port/redis-migrate-tool/ redis-shake :
这几个工具功能相近,可支持redis的实时数据同步。本文以redis-shake来重点介绍。
2. Redis-shake 介绍
2.1 Redis-shake简介
redis-shake是阿里云自研的开源工具,支持对Redis数据进行解析(decode)、恢复(restore)、备份(dump)、同步(sync/rump)。在sync模式下,redis-shake使用SYNC或PSYNC命令将数据从源端Redis同步到目的端Redis,支持全量数据同步和增量数据同步,增量同步在全量同步完成后自动开始。
功能介绍:
- 备份dump:将源redis的全量数据通过RDB文件备份起来。
- 解析decode:对RDB文件进行读取,并以json格式解析存储。
- 恢复restore:将RDB文件恢复到目的redis数据库。
- 同步sync: 支持源redis和目的redis的数据同步,支持全量和增量数据的迁移。支持单节点、主从版、集群版之间的互相同步。需要注意的是,如果源端是集群版,可以启动一个RedisShake,从不同的db结点进行拉取,同时源端不能开启move slot功能;对于目的端,如果是集群版,写入可以是1个或者多个db结点。
- 同步rump:支持源redis和目的redis的数据同步,仅支持全量的迁移。采用scan和restore命令进行迁移,支持不同云厂商不同redis版本的迁移。
2.2 基本原理
redis-shake的基本原理就是模拟一个从节点加入源redis集群,首先进行全量拉取并回放,然后进行增量的拉取(通过psync命令)。如下图所示:
如果源端是集群模式,只需要启动一个redis-shake进行拉取,同时不能开启源端的move slot操作。如果目的端是集群模式,可以写入到一个结点,然后再进行slot的迁移,当然也可以多对多写入。
2.3 软件安装
软件下载地址: https://github.com/alibaba/RedisShake/releases 。软件解压缩后就可使用。
安装:
#安装redis-shake
$wget 'https://github.com/alibaba/RedisShake/releases/download/release-v1.6.24-20191220/redis-shake-1.6.24.tar.gz' .
$tar -zxvf redis-shake-1.6.24.tar.gz
$mv redis-shake-1.6.24 /usr/local/redis-shake
#环境变量
$echo 'export PATH=$>/etc/profile'>PATH:/usr/local/redis-shake'>>/etc/profile
$source /etc/profile
#查看版本
$redis-shake --version
#启动程序, xxx为sync, restore, dump, decode, rump之一
$redis-shake.linux -conf=redis-shake.conf -type=xxx
#目录中文件信息
$tree /usr/local/redis-shake
.
├── ChangeLog
├── redis-shake.conf
├── redis-shake.darwin
├── redis-shake.linux
├── redis-shake.windows
├── start.sh
└── stop.sh
启动:
redis-shake --conf={配置文件地址} --type={模式:sync/dump等} 模式需要与配置文件中的source target对应。模式为sync, restore, dump, decode, rump其中之一,全量+增量同步请选择sync。 mac下请使用redis-shake.darwin,windows请用redis-shake.windows
2.4 配置参数
2.4 模式说明
2.4.1 dump模式
配置参数:
参数 | 说明 | 示例 |
---|---|---|
source.address | 源Redis的连接地址与服务端口。 | xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379 |
source.password_raw | 源Redis的连接密码。 | account:password |
rdb.output | 输出的RDB文件名称。 | local_dump |
测试:
导出redis 192.124.64.212:6001的数据。
$vim redis-shake-dump.conf
# source相关配置[cluster|standalone]
source.type = standalone
source.address = 192.124.64.212:6001
source.password_raw = pwd123
source.auth_type = auth
# 如果是decode或者dump,这个参数表示输出的rdb前缀,比如输入有3个db,那么dump分别是:
# ${output_rdb}.0, ${output_rdb}.1, ${output_rdb}.2
target.rdb.output = local_dump
#执行
$redis-shake -type=dump -conf=redis-shake-dump.conf
#检查日志
tail -f /var/log/redis-shake.log
2020/01/12 23:49:13 [INFO] routine[3] total = 15.212KB - 15.212KB [100%]
2020/01/12 23:49:13 [INFO] routine[3] dump: rdb done
2020/01/12 23:49:13 [INFO] execute runner[*run.CmdDump] finished!
说明:
- 日志中出现execute runner[*run.CmdDump] finished!表示RDB文件备份完成。
- RDB文件名称默认为local_dump.0,可使用cat local_dump.0命令确认Redis数据是否备份成功。
2.4.2 decode模式
官网说decode实现对RDB文件进行读取,并以json格式解析存储。(本文作者没有搞明白如何用decode redis rdb文件为json文件 ,故我使用了类似的工具redis-rdb-tools. )
测试:
$vim redis-shake-decode.conf
id = redis-shake
# used in `decode` and `restore`.
# if the input is list split by semicolon(;), redis-shake will restore the list one by one.
source.rdb.input = ./local_dump.0
#执行:
$redis-shake -type=decode -conf=redis-shake-decode.conf
redis-rdb-tools:
解析redis的dump.rdb文件,分析内存,以JSON格式导出数据。
#安装
$pip install rdbtools python-lzf
#wget https://github.com/sripathikrishnan/redis-rdb-tools/archive/master.zip
#帮助
$rdb -h
#使用
#解析dump文件并以JSON格式标准输出
$rdb --command json data/redis-6379.rdb
$rdb --db 0 --command json --key "foo*" data/redis-6379.rdb
#生成内存报告
$rdb -c memory data/redis-6379.rdb > redis_mem_report.csv
2.4.3 restore模式
restore模式可将RDB文件恢复到目的redis数据库。主要需要配置source.input.rdb表示输入的rdb文件列表(分号";"分割),同时配置target.type, target.address和target.password_raw表示恢复的地址。
配置参数:
参数 | 说明 | 示例 |
---|---|---|
rdb.input | 备份文件(RDB文件)的路径,可使用相对路径或绝对路径。 | ./demo.rdb |
target.address | 目的Redis的连接地址与端口号。 | ip:6379 |
target.password_raw | 目的Redis的连接密码。 | TargetPass233 |
target.db | 设置待迁移的数据在目的Redis中的的逻辑数据库名,默认值为-1。当该值设置为-1时,逻辑数据库名在源Redis和目的Redis中的名称相同,即源DB0将被迁移至目的Redis中的DB0,DB1将被迁移至DB1。 | -1 |
rewrite | 如果目的Redis有与RDB文件中相同的key,是否覆盖,可选值:true(覆盖);false(不覆盖)。 | 说明 默认为true,如设置为false且存在数据冲突则会出现异常提示。 |
parallel | RDB文件同步中使用的并发线程数,用于提高同步性能。 | 最小值为1,推荐值为64 |
测试:
$vim redis-shake-restore.conf
id = redis-shake
# used in `decode` and `restore`.
# if the input is list split by semicolon(;), redis-shake will restore the list one by one.
# 如果是decode或者restore,这个参数表示读取的rdb文件。支持输入列表,例如:rdb.0;rdb.1;rdb.2
source.rdb.input = ./local_dump.0
target.type= standalone
target.address = 10.124.64.212:6001
target.password_raw = pwd123
target.auth_type = auth
target.db = -1
# 在rdb全量同步阶段,如果目标redis已经存在对应的key时是否覆盖,如果为false就抛异常
rewrite = true
#执行
$redis-shake -type=restore -conf=redis-shake-restore.conf
#日志
tail -f /var/log/redis-shake.log
2020/01/13 17:06:43 [INFO] db_size:3 expire_size:0
2020/01/13 17:06:43 [INFO] routine[0] total = 218B - 218B [100%] entry=3
2020/01/13 17:06:43 [INFO] routine[0] restore: rdb done
2020/01/13 17:06:43 [INFO] restore from '[./local_dump.0]' to '[10.124.64.212:6001]' done
2020/01/13 17:06:43 [INFO] Enabled http stats, set status (incr), and wait forever.
2.4.4 sync模式
redis-shake sync模式参数说明:
参数 | 说明 | 示例 |
---|---|---|
source.address | 源Redis的连接地址与服务端口。 | xxx.xxx.1.10:6379 |
source.password_raw | 源Redis的连接密码。 | SourcePass233 |
target.address | 目的Redis的连接地址与服务端口。 | xx.redis.rds.aliyuncs.com:6379 |
target.password_raw | 目的Redis的连接密码。 | TargetPass233 |
rewrite | 如果目的Redis有相同的key,是否覆盖,可选值:true(覆盖);false(不覆盖)。 | 默认为true,为false且存在数据冲突则会出现异常提示。 |
target.db | 待迁移的数据在目的Redis中的逻辑数据库名。当该值设置为-1时,源Redis和目的Redis中的名称相同 | -1 |
parallel | RDB文件同步中使用的并发线程数,用于提高同步性能。 | 最小值为1,推荐值为64 |
$vim redis-shake-cluster.conf
2.4.5 rump模式
rump模式支持源redis和目的redis的数据同步,仅支持全量的迁移。采用scan和restore命令进行迁移,支持不同云厂商不同redis版本的迁移。
2.5 监控
- restful监控指标 https://github.com/alibaba/RedisShake/wiki/
$curl 127.0.0.1:9320/metric | python -m json.tool
3. 环境准备
3.1 环境规划
3.2 redis-cluster安装
4. Redis-Cluster迁移
参考:
- https://redis.io/
- http://www.redis.cn/topics/cluster-spec.html
- https://github.com/alibaba/RedisShake
- https://yq.aliyun.com/articles/691794
- https://yq.aliyun.com/articles/690463
- https://help.aliyun.com/document_detail/111066.html
- https://github.com/sripathikrishnan/redis-rdb-tools/
- http://blog.chinaunix.net/uid-1757778-id-3977331.html
- https://www.redinav.com/
- https://my.oschina.net/ruoli/blog/2252393