1. 迁徙工具比对

  1. redis-migrate-tool

    redis-migrate-tool是唯品会开源的一款Redis异构集群之间的数据实时迁徙工具,不过曾经有两年没有更新了,我集体感觉这是一款比较完善的工具,特地是数据校验,具体性能介绍见GitHub:参考地址

  2. RedisShake

    RedisShake是阿里云基于豌豆荚开源的redis-port进行二次开发的一个反对Redis异构集群实时同步的工具,它和redis-migrate-tool相比拟,我感觉它的长处在于反对前缀key的同步,反对多DB同步,而redis-migrate-tool 只能全量同步,并且如果源做了分库,同步到指标Redis的时候都同步到了db0一个库外面了,这对于做了分库场景的业务是不可行的,对于RedisShake的具体性能介绍见GitHub:参考地址

  3. redis-port
    redis-port是豌豆荚当年为了让大家不便从redis迁徙到Codis开源的一个Redis数据迁徙工具,当初也曾经很久没更新了,对于它的性能也用能够参见GitHub:参考地址

2. 迁徙工具装置与配置

  1. RedisShake 的装置

    间接下载二进制包进行装置:

    下载地址

  2. 配置文件批改

    redis-shake.conf配置文件:

    # 以后配置文件的版本号,请不要批改该值。conf.version = 1# ------------------------------------------------------# idid = redis-shake# log file,日志文件,不配置将打印到stdout (e.g. /var/log/redis-shake.log )log.file =# log level: "none", "error", "warn", "info", "debug". default is "info".log.level = info# pid path,过程文件存储地址(e.g. /var/run/),不配置将默认输入到执行上面,# 留神这个是目录,真正的pid是`{pid_path}/{id}.pid`pid_path = # pprof port.system_profile = 9310# restful port, set -1 means disable, in `restore` mode RedisShake will exit once finish restoring RDB only if this value# is -1, otherwise, it'll wait forever.# restful port,查看metric端口, -1示意不启用,如果是`restore`模式,只有设置为-1才会在实现RDB复原后退出,否则会始终block。http_profile = 9320# parallel routines number used in RDB file syncing. default is 64.# 启动多少个并发线程同步一个RDB文件。parallel = 32# 源端redis的类型,反对standalone,sentinel,cluster和proxy四种模式,留神:目前proxy只用于rump模式。source.type = sentinel# 源redis地址。对于sentinel或者开源cluster模式,输出格局为"master名字:拉取角色为master或者slave@sentinel的地址",别的cluster# 架构,比方codis, twemproxy, aliyun proxy等须要配置所有master或者slave的db地址。source.address = mymaster:master@10.10.20.101:26379;10.10.20.102:26379;10.10.20.103:26379# password of db/proxy. even if type is sentinel.source.password_raw = # auth type, don't modify itsource.auth_type = auth# tls enable, true or false. Currently, only support standalone.# open source redis does NOT support tls so far, but some cloud versions do.source.tls_enable = false# input RDB file.# 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# redis-shake将会挨个进行复原。source.rdb.input = local# 如果db节点/输出的rdb有5个,但rdb.parallel=3,那么一次只会# 并发拉取3个db的全量数据,直到某个db的rdb拉取结束并进入增量,才会拉取第4个db节点的rdb,# 以此类推,最初会有len(source.address)或者len(rdb.input)个增量线程同时存在。source.rdb.parallel = 0# for special cloud vendor: ucloud# used in `decode` and `restore`.# ucloud集群版的rdb文件增加了slot前缀,进行特判剥离: ucloud_cluster。source.rdb.special_cloud = # 目标redis的类型,反对standalone,sentinel,cluster和proxy四种模式。target.type = clustertarget.address = 10.10.20.101:7000;10.10.20.102:7000;10.10.20.103:7000# password of db/proxy. even if type is sentinel.target.password_raw = Redis1234{}# auth type, don't modify ittarget.auth_type = auth# all the data will be written into this db. < 0 means disable.target.db = 0# tls enable, true or false. Currently, only support standalone.# open source redis does NOT support tls so far, but some cloud versions do.target.tls_enable = false# output RDB file prefix.# used in `decode` and `dump`.# 如果是decode或者dump,这个参数示意输入的rdb前缀,比方输出有3个db,那么dump别离是:# ${output_rdb}.0, ${output_rdb}.1, ${output_rdb}.2target.rdb.output = local_dump# e.g., target.version = 4.0target.version =# 用于解决过期的键值,当迁徙两端不统一的时候,目标端须要加上这个值fake_time =# 当源目标有反复key,是否进行覆写# rewrite示意源端笼罩目标端。# none示意一旦产生过程间接退出。# ignore示意保留目标端key,疏忽源端的同步key。该值在rump模式下没有用。key_exists = rewrite# 指定的db被通过,比方0;5;10将会使db0, db5, db10通过, 其余的被过滤filter.db.whitelist =# 指定的db被过滤,比方0;5;10将会使db0, db5, db10过滤,其余的被通过filter.db.blacklist =# 反对按前缀过滤key,只让指定前缀的key通过,分号分隔。比方指定abc,将会通过abc, abc1, abcxxxfilter.key.whitelist =# 反对按前缀过滤key,不让指定前缀的key通过,分号分隔。比方指定abc,将会阻塞abc, abc1, abcxxxfilter.key.blacklist =# filter given slot, multiple slots are separated by ';'.# e.g., 1;2;3# used in `sync`.# 指定过滤slot,只让指定的slot通过filter.slot =# filter lua script. true means not pass. However, in redis 5.0, the lua # converts to transaction(multi+{commands}+exec) which will be passed.# 管制不让lua脚本通过,true示意不通过filter.lua = false# 失常key如果不大,那么都是间接调用restore写入到目标端,如果key对应的value字节超过了给定# 的值,那么会分批顺次一个一个写入。如果目标端是Codis,这个须要置为1,具体起因请查看FAQ。# 如果目标端大版本小于源端,也倡议设置为1。big_key_threshold = 524288000# enable metric# used in `sync`.# 是否启用metricmetric = true# print in log# 是否将metric打印到log中metric.print_log = false# sender information.# sender flush buffer size of byte.# used in `sync`.# 发送缓存的字节长度,超过这个阈值将会强行刷缓存发送sender.size = 104857600# sender flush buffer size of oplog number.# used in `sync`. flush sender buffer when bigger than this threshold.# 发送缓存的报文个数,超过这个阈值将会强行刷缓存发送,对于目标端是cluster的状况,这个值# 的调大将会占用局部内存。sender.count = 4095# 用于metric统计时延的队列sender.delay_channel_size = 65535# enable keep_alive option in TCP when connecting redis.# the unit is second.# 0 means disable.# TCP keep-alive保活参数,单位秒,0示意不启用。keep_alive = 0# 每次scan的个数,不配置则默认100.scan.key_number = 50# 有些版本具备非凡的格局,与一般的scan命令有所不同,咱们进行了非凡的适配。目前反对腾讯云的集群版"tencent_cluster"# 和阿里云的集群版"aliyun_cluster",正文主从版不须要配置,只针对集群版。scan.special_cloud =# used in `rump`.# we support to fetching data from given file which marks the key list.# 有些云版本,既不反对sync/psync,也不反对scan,咱们反对从文件中进行读取所有key列表并进行抓取:一行一个key。scan.key_file =# limit the rate of transmission. Only used in `rump` currently.# e.g., qps = 1000 means pass 1000 keys per second. default is 500,000(0 means default)qps = 200000# enable resume from break point, please visit xxx to see more details.# 断点续传开关resume_from_break_point = false# replace hash tag.# used in `sync`.replace_hash_tag = false

次要配置项阐明:

# 源Redis的类型,哨兵模式采纳sentinelsource.type = sentinel# 源Redis的地址信息,如果是哨兵, 格局:哨兵名称:主从标识@节点地址信息source.address = mymaster:master@10.10.20.101:26379;10.10.20.102:26379;10.10.20.103:26379# 源Redis的明码信息,没有明码认证,留空即可source.password_raw = # 源Redis的认证标识,不论有无明码认证, 都不必批改source.auth_type = auth# 指标Redis的类型,这里所填的指标是集群target.type = cluster# 指标Redis的地址信息,多个地址以;分号分隔,留神这里要填的对立为主节点或从节点信息target.address = 10.10.20.101:7000;10.10.20.102:7000;10.10.20.103:7000# 指标Redis的明码信息target.password_raw = Redis1234{}# 指标Redis的认证标识, 不必批改target.auth_type = auth# 指标Redis的存储数据库,如果为正数,代表不启用该性能,如果指定某个库,会将源数据全副写入target.db = 0# 当存在雷同的keys,解决计划:# rewrite示意源端笼罩目标端。# none示意一旦产生过程间接退出。# ignore示意保留目标端key,疏忽源端的同步key。该值在rump模式下没有用。key_exists = rewrite

3. 数据同步解决

  1. 数据同步命令

    ./redis-shake -conf=redis-shake.conf -type=sync

type能够反对sync, restore, dump, decode, rump。全量+增量同步抉择sync

  1. 日志后果信息

    同步分为三个阶段:

    A. 期待源端save rdb结束,日志如下

    2019/06/06 15:14:56 [INFO] dbSyncer[0] + waiting source rdb2019/06/06 15:14:57 [INFO] dbSyncer[0] - waiting source rdb2019/06/06 15:14:57 [INFO] dbSyncer[0] + waiting source rdb

B. 全量同步阶段,显示百分比:

2019/06/06 15:15:41 [INFO] dbSyncer[0] total=924836132 -      9155943 [  0%]  entry=21092019/06/06 15:15:42 [INFO] dbSyncer[0] total=924836132 -     16107663 [  1%]  entry=44112019/06/06 15:15:43 [INFO] dbSyncer[0] total=924836132 -     22914262 [  2%]  entry=67502019/06/06 15:15:44 [INFO] dbSyncer[0] total=924836132 -     29707595 [  3%]  entry=90602019/06/06 15:15:45 [INFO] dbSyncer[0] total=924836132 -     35741354 [  3%]  entry=110672019/06/06 15:15:46 [INFO] dbSyncer[0] total=924836132 -     42911547 [  4%]  entry=13480

C. 增量同步,呈现字样sync rdb done后,以后dbSyncer进入增量同步:

2019/07/09 16:34:05 [INFO] dbSyncer[0] sync:  +forwardCommands=1      +filterCommands=0      +writeBytes=42019/07/09 16:34:06 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=02019/07/09 16:34:07 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=02019/07/09 16:34:08 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=02019/07/09 16:34:09 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=02019/07/09 16:34:10 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=02019/07/09 16:34:11 [INFO] dbSyncer[0] sync:  +forwardCommands=0      +filterCommands=0      +writeBytes=0

其中forwardCommands示意发送的命令个数,filterCommands示意过滤的命令个数,比方opinfo或者指定了filter都会被过滤,writeBytes示意发送的字节数。

4. 数据校验解决

  1. 数据校验工具

    redis-full-check通过全量比照源端和目标端的redis中的数据的形式来进行数据校验。

    Redis-full-check

    下载地址

  2. 校验执行命令

    ./redis-full-check -s '10.10.20.102:6379' -p '' -t '10.10.20.101:7000;10.10.20.102:7000;10.10.20.103:7000'  -a 'Redis1234{}' --targetdbtype=1 --metric  --result=result.1            

配置同步源地址与指标地址信息,开启metric会输入剖析信息, result会将校验后果做汇总记录。

具体参数阐明:

  -s, --source=SOURCE               源redis库地址(ip:port),如果是集群版,那么须要以分号(;)宰割不同的db,只须要配置主或者从的其中之一。例如:10.1.1.1:1000;10.2.2.2:2000;10.3.3.3:3000。  -p, --sourcepassword=Password     源redis库明码      --sourceauthtype=AUTH-TYPE    源库管理权限,开源reids下此参数无用。      --sourcedbtype=               源库的类别,0:db(standalone单节点、主从),1: cluster(集群版),2: 阿里云      --sourcedbfilterlist=         源库须要抓取的逻辑db白名单,以分号(;)宰割,例如:0;5;15示意db0,db5和db15都会被抓取  -t, --target=TARGET               目标redis库地址(ip:port)  -a, --targetpassword=Password     目标redis库明码      --targetauthtype=AUTH-TYPE    目标库管理权限,开源reids下此参数无用。      --targetdbtype=               参考sourcedbtype      --targetdbfilterlist=         参考sourcedbfilterlist  -d, --db=Sqlite3-DB-FILE          对于差别的key存储的sqlite3 db的地位,默认result.db      --comparetimes=COUNT          比拟轮数  -m, --comparemode=                比拟模式,1示意全量比拟,2示意只比照value的长度,3只比照key是否存在,4全量比拟的状况下,疏忽大key的比拟      --id=                         用于打metric      --jobid=                      用于打metric      --taskid=                     用于打metric  -q, --qps=                        qps限速阈值      --interval=Second             每轮之间的工夫距离      --batchcount=COUNT            批量聚合的数量      --parallel=COUNT              比拟的并发协程数,默认5      --log=FILE                    log文件      --result=FILE                 不统一后果记录到result文件中,格局:'db    diff-type    key    field'      --metric=FILE                 metric文件      --bigkeythreshold=COUNT       大key拆分的阈值,用于comparemode=4  -f, --filterlist=FILTER           须要比拟的key列表,以分号(;)宰割。例如:"abc*|efg|m*"示意比照'abc', 'abc1', 'efg', 'm', 'mxyz',不比照'efgh', 'p'。  -v, --version
  1. 查看比对后果

    查看result后果信息:

    [root@localhost redis-full-check-1.4.8]# less result.1 

校验后果:

0       lack_target     single23        1       lack_target     test    9       value   single2

第一列代表数据库编号, 第二列代表抵触类型, 第三列代表抵触的key。

抵触类型蕴含:

lack_soure: field存在于源端key,field不存在与目标端key。

lack_target: field不存在与源端key,field存在于目标端key。

value: field存在于源端key和目标端key,然而field对应的value不同。

要查看更为具体的信息, 能够通过sqlite查问:

[root@localhost redis-full-check-1.4.8]# sqlite3 result.db.3SQLite version 3.7.17 2013-05-20 00:56:22Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite> .tablesFINAL_RESULT  field         key         sqlite> select * from key;1|single23|string|lack_target|0|2|02|test|string|lack_target|1|4|03|single2|string|value|9|1|9

信息列对应关系: id, key, type, conflict_type, db, source_len, target_len


本文由mirson创作分享,如需进一步交换,请加QQ群:19310171或拜访www.softart.cn