aws-redis数据非实时迁移

一、背景

因为一套环境要迁移到aws redis上,原本打算采用rdb上传到s3中,然后在创建新集群的时候使用s3种子的方式将rdb文件加载到新的集群中,这样比较方便快捷,但是遇到了两个问题,
问题一是在大的rdb文件应用时会出现创建失败,
这是因为我从单点迁移到集群的时候,单点中不只db0有数据,而其他库也有数据,但集群只有db0,所以出现了问题
问题二是这种方法没有办法实时同步,无法达到想要的平滑切换的效果

二、使用工具

工具名:redis-shake

1.下载

下载地址:https://github.com/alibaba/RedisShake/tags

 wget https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz

2.解压

tar xzf redis-shake-v2.0.3.tar.gz

3.编辑配置文件

cd redis-shake-v2.0.3
vim redis-shake.conf

4.配置文件详解

参数名 解释
source.type 根据源库(自建数据库)的架构选择,取值:standalone:主从架构。cluster:集群架构。
source.address 源库的连接地址和端口号,连接地址和端口号之间使用英文冒号(:)分隔。
source.password_raw 源库的密码,如果源库未设置密码,无需填写
target.type 同source.type
target.address 同source.address
target.password_raw 同source.password_raw
target.db 将源库中所有库的数据都迁移至目标库的指定库中,取值范围为0~15。说明 默认值为-1,表示不启用该功能。
key_exists 当源库中的Key与目标库中的Key相同时,采取的数据写入策略,取值:rewrite:覆盖写入至目标库。none:默认值,停止运行Redis-shake程序并提示冲突的Key。ignore:直接跳过当前迁移的Key,保留目标库的数据,继续执行数据迁移
filter.db.whitelist 需要迁移的库名,多个库名间用英文分号(;)分隔,默认为空,即迁移所有库。例:0;1
filter.db.blacklist 不需要迁移的库名(即黑名单),多个库名间用英文分号(;)分隔。默认为空,即不设置黑名单。例:0;1
parallel Redis-shake执行迁移的并发线程数,适当调大该值可提高同步性能

5.配置文件示例

# 单点
source.type = standalone
source.address = redis_ip:redis_port
# password of db/proxy. even if type is sentinel.
source.password_raw = password
# 集群
target.type = cluster
target.address = redis_ip:redis_port;redis_ip:redis_port;redis_ip:redis_port
# 如果没有密码则可以不用填
target.password_raw =
key_exists = rewrite

5.1.启动

5.1.1 普通启动方式

 nohup ./redis-shake.linux -conf=redis-shake.conf -type=sync &

5.1.2 因为有些云数据库禁止了sync命令,所以只能通过rump的方式来启动了

./redis-shake.linux -type=rump -conf=redis-shake.conf

对比工具链接: https://blog.csdn.net/line_on_database/article/details/119564749

6.错误及解决方案

6.1
**Q:同步时候出现报错**
2021/07/23 09:27:33 [PANIC] read error, please check source redis log or network
[error]: EOF
[stack]:
    1   /Users/tongyao.lty/Work/RedisShake/src/redis-shake/common/utils.go:930
            redis-shake/common.Iocopy
    0   /Users/tongyao.lty/Work/RedisShake/src/redis-shake/dbSync/syncBegin.go:92
            redis-shake/dbSync.(*DbSyncer).runIncrementalSync

查看源端redis日志
events=rw cmd=psync scheduled to be closed ASAP for overcoming of output buffer limits.

解决办法:
config set client-output-buffer-limit 'normal 0 0 0 slave 0 0 0 pubsub 268435456 67108864 60'


github上的问题解答:https://github.com/alibaba/RedisShake/wiki/常见问题?spm=a2c4g.11186623.2.28.42012b83tcBOfH#2-报错问题解决
6.2
Q: 是否支持断点续传?
A: 目前支持主从版和部分集群版,具体请查看wiki上相应的文档。

6.3
Q: 对于某些云上redis,比如部分云厂商不支持sync/psync权限,如何进行迁移?
A: 从v1.4版本开始,我们支持了rump模式进行扫描迁移,可以应对sync/psync权限没有开放的场景。该种模式只支持全量,不支持增量。具体请参考wiki上的使用文档。

6.4
Q: 为什么我的源端主从有0-15,一共16个逻辑db,而同步到目的端的集群版就只有db0了?
A: 因为集群版只支持db0,所以db1-15的数据都不会同步到目的端。


6.5
Q: 如何过滤lua脚本?
A: 从v1.6.9版本开始,用户可以设置filter.lua参数进行过滤,具体请参考配置文件的说明。而在5.0的redis版本中,所有的lua都会转换为事务操作,就不能被过滤了。

6.6
Q: 如果启用过滤key的功能?
A: 用户可以设定filter.key.whitelist让指定前缀的key通过,也可以指定filter.key.blacklist让指定前缀的key不通过,其余的通过。注意这2个参数只能最多指定其中一个。例如,filter.key.whitelist = abc;xxx;efg会让abc,abc1,xxxyyyy通过,而kkk,mmm都不会通过。

6.7
Q: RedisShake是否支持codis和twemproxy?
A: 支持。不过请设置big_key_threshold = 1,以及启用filter.lua = true。

6.8
Q: 如何控制同步的并发数?
A: 用户可以通过source.rdb.parallel参数控制同步的并发数,比如source.rdb.parallel = 4表示一次只会通过4个全量,只有当其中一个全量同步完成以后,才会开启新的一个全量同步。举个例子,比如源端有8个分片,设置4的话表示同一时刻只会同步4个,假如第1个全量完成了(restore模式完成或者sync模式进入增量),那么会开启第5个全量同步,以此类推直到所有的都完成或者进入增量同步。

6.9
Q: 是否支持db映射,比如源端的db2同步到目的端的db10?
A: 不支持,目前只支持所有源端db同步到目的端一个db,比如设置target.db = 10,那么所有源端的逻辑db都会同步到目的端的db10。


6.10

Q: decode Redis resp failed. [error]: EOF
A: 如果用户源端从slave上进行拉取的,而源端master跟slave的连接断开了,那么从slave拉取就会失败。

6.11
Q: [PANIC] read sync response = ''. EOF
A: 用户需要检查源端redis节点的日志,通常来说,是源端已经save rdb期间,拒绝掉新来的psync请求,可能发生在某些redis版本。用户需要等待一段时间再重试。

6.12
Q: -ERR Can\'t SYNC while not connected with my master
A: 参见上面这个EOF的问题。

6.13
Q: target key name is busy
A: 目的端对应的key已经存在。解决方法有如下三种,可任选其一:
删除目的端报错的key。
启用key_exists = rewrite(源端Key覆盖目的端,v1.6.27版本开始支持,在v1.6.27之前是rewrite = true)
启用key_exists = ignore(忽略报错的key,v1.6.27版本开始支持)

6.14
Q: -ERR Unable to perform background save
A: 请检查源端redis日志,源端bgsave失败,通常是内存不够了,或者磁盘写入失败。

6.15
Q: OOM command not allowed when used memory > 'maxmemory'
A: 写入到目的端的时候,内存超过原来规格。

6.16
Q: [PANIC] parse rdb entry error, if the err is :EOF, please check that if the src db log has client outout buffer oom, if so set output buffer larger
A: 请检查源端redis日志,通常是全量同步过久或者增量过大,导致output buffer打满。通常解决办法有如下几种:

增大shake全量同步的并发度,调高parallel。
修改增大源端output buffer的大小, 通过修改output-buffer-limit参数。(建议采用这种方式)
在业务低峰期再进行同步。


6.17
Q: restore command error key:xxx err:-ERR server closed connection
A: 意味着目的端把连接给关闭了,如果是写的key过大导致的,可以降低big_key_threshold对key进行拆分。


6.18
Q: [PANIC] auth failed[-ERR unknown command '']
A: 设置source.auth_type = auth和target.auth_type = auth。这个问题在v2.6.26版本已经修复掉了,参加:https://github.com/alibaba/RedisShake/issues/237


6.19
Q: ERR redis tempory failure
A: 对于某些集群版,比如阿里云,如果后台db节点发生过主从切换,会报错这个。


6.20
Q: Error: NOSCRIPT No matching script. Please use EVAL
A: 这个通常发生在目的端。这个错误表示对应的lua脚本已经丢失了。在redis版本v4.0.4以后这个问题不会出现,在4.0.4以前,源端连接的是slave节点,是可能会出现这个问题的。解决方法如下选一:
源端升级到4.0.4以后的版本
源端连接master。
手动在目的端添加缺失的lua脚本
源端启用redis.replicate_commands()

6.21
Q: checksum validation failed
A: 源端redis禁用了checksum选项,可以通过config set rdbchecksum进行开启。


6.22
Q: ERR 'EVAL' command keys must in the same slot
A: lua脚本操作的key不位于同一个slot,通常出现在目的端为集群版的情况。用户可以自己修改Lua脚本,或者将涉及到的key通过hashtag等手段划到一个slot内部。


6.23
Q: Conf.Options check failed: get target redis version failed[EOF]
A: 对于某些版本比如twemproxy,不支持获取目的端的redis版本。用户可以通过设置target.version强制设定目的端版本。


6.24
Q: ERR syntax error
A: 通常出现在目的端redis版本小于源端redis的版本,所以部分数据格式不兼容。


6.25
Q: [xxx] redis address should be all masters or all slaves, master:[xxx], slave[xxx]
A: 如果用户输入的是集群版,需要只输入master或者只slave,指定的角色不能既有master又有slave。参加issue#149



6.26
Q: do dump with failed[EOF]
A: 源端redis断开连接,用户需要检查源端redis的日志情况。通常是某个key过大,比如超过了512M(没有办法解决),或者output buffer打满导致的。


6.27
Q: Error: CROSSSLOT Keys in request don\'t hash to the same slot
A: 这个表示后用户的单次请求里面的key没有分发到一个slot,而这个是redis集群本身的强约束。在redis-shakev1.6.27开始,放开了部分命令的约束,从一个slot放开到一个分片db。


6.28
Q: ERR DUMP payload version or checksum are wrong
A: 通常出现在rump模式,源端版本大于目的端版本,比如源端是4.0,目的端2.8,某些数据结构格式已经修改导致无法同步。用户可以设置big_key_threshold = 1绕过这个限制。


6.29
Q: [PANIC] restore command response = \'ECONNTIMEOUT: dial tcp xxx:1000: connect: cannot assign requested address', should be 'OK'
A: 本机端口耗尽了,需要排查一下原因。


6.30
Q: ERR syntax error
A: 同样出现在源端版本大于目的端版本的情况,比如源端是4.0,目的端2.8。


6.31
Q: run ChooseNodeWithCmd failed[transaction command[xxxx] key[yyyyy] not hashed in the same slot]
A: 事务中的key需要分发到一个slot里面,通常出现在源端形态和目的端不一致(比如源端是主从,目的端是集群),或者源端集群版的slot分布和目的端不一致。


6.32
Q: return error[ERR Bad data format], ignore it and try to split the value
A: 同样出现在源端版本大于目的端版本的情况,比如源端是4.0,目的端2.8。用户可以设置big_key_threshold = 1绕过这个限制。


6.33
Q: lua同步报错?
A: 常见报错如下:
ERR bad lua script for redis cluster, first parameter of redis.call/redis.pcall must be a single literal string
\"-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array\r\n"`
\"-ERR for redis cluster, eval/evalsha number of keys can\'t be negative or zero\r\n\"
"-ERR eval/evalsha command keys must in same slot\r\n"
出现在目的端为阿里云集群版的情况。基本上的问题都是用户没有按照集群版的规范编写lua脚本,通常发生在主从变配到集群的时候,目前redis-shake版本已经支持对导入出错的lua进行过滤
云上redis-shake版本请在配置文件中设置"filter.lua = 2"再重启redis-shake即可,通常还需要再加上"rewrite = true"。
开源redis-shake版本请设置filter.lua = true,通常还需要加上rewrite = true(1.6.27以前的版本),或者key_exists = rewrite(1.6.27及以后的版本)。
Q: ERR unknown command 'ISCAN'

A: 这个是用户配置项里面添加了scan.special_cloud = aliyun_cloud选项,这个选项是只针对阿里云的集群版的,如果源端是主从版,请去掉该选项。

6.34

Q: ERR command replconf not support for your account

A: 源端如果是阿里云的版本会报错这个,对于主从版需要在控制台申请复制权限,用申请到的密码贴到source.password_raw里面;对于集群版,目前还不支持复制权限,所以用户只能使用rump模式进行全量的扫描迁移,不支持增量。

你可能感兴趣的:(AWS,redis学习,redis)