因为一套环境要迁移到aws redis上,原本打算采用rdb上传到s3中,然后在创建新集群的时候使用s3种子的方式将rdb文件加载到新的集群中,这样比较方便快捷,但是遇到了两个问题,问题一是在大的rdb文件应用时会出现创建失败,问题二是这种方法没有办法实时同步,无法达到想要的平滑切换的效果
工具名:redis-shake
下载地址: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
tar xzf redis-shake-v2.0.3.tar.gz
cd redis-shake-v2.0.3 vim redis-shake.conf
参数名 | 解释 |
---|---|
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执行迁移的并发线程数,适当调大该值可提高同步性能 |
# 单点 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
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模式进行全量的扫描迁移,不支持增量。