redis-migrate-toolgit
redis-migrate-tool是惟品會開源的一款Redis異構集羣之間的數據實時遷移工具,不過已經有兩年沒有更新了,我我的以爲這是一款比較完善的工具,特別是數據校驗,詳細功能介紹見GitHub:參考地址github
RedisShakeredis
RedisShake是阿里雲基於豌豆莢開源的redis-port進行二次開發的一個支持Redis異構集羣實時同步的工具,它和redis-migrate-tool相比較,我以爲它的優勢在於支持前綴key的同步,支持多DB同步,而redis-migrate-tool 只能全量同步,而且若是源作了分庫,同步到目標Redis的時候都同步到了db0一個庫裏面了,這對於作了分庫場景的業務是不可行的,關於RedisShake的詳細功能介紹見GitHub:參考地址sql
RedisShake 的安裝數據庫
直接下載二進制包進行安裝:緩存
下載地址restful
配置文件修改架構
redis-shake.conf配置文件:併發
# 當前配置文件的版本號,請不要修改該值。 conf.version = 1 # ------------------------------------------------------ # id id = 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 it source.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 = cluster target.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 it target.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}.2 target.rdb.output = local_dump # e.g., target.version = 4.0 target.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, abcxxx filter.key.whitelist = # 支持按前綴過濾key,不讓指定前綴的key經過,分號分隔。好比指定abc,將會阻塞abc, abc1, abcxxx filter.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`. # 是否啓用metric metric = 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
主要配置項說明:less
# 源Redis的類型,哨兵模式採用sentinel source.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
數據同步命令
./redis-shake -conf=redis-shake.conf -type=sync
type能夠支持sync, restore, dump, decode, rump。全量+增量同步選擇sync
日誌結果信息
同步分爲三個階段:
A. 等待源端save rdb完畢,日誌以下
2019/06/06 15:14:56 [INFO] dbSyncer[0] + waiting source rdb 2019/06/06 15:14:57 [INFO] dbSyncer[0] - waiting source rdb 2019/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=2109 2019/06/06 15:15:42 [INFO] dbSyncer[0] total=924836132 - 16107663 [ 1%] entry=4411 2019/06/06 15:15:43 [INFO] dbSyncer[0] total=924836132 - 22914262 [ 2%] entry=6750 2019/06/06 15:15:44 [INFO] dbSyncer[0] total=924836132 - 29707595 [ 3%] entry=9060 2019/06/06 15:15:45 [INFO] dbSyncer[0] total=924836132 - 35741354 [ 3%] entry=11067 2019/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=4 2019/07/09 16:34:06 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0 2019/07/09 16:34:07 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0 2019/07/09 16:34:08 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0 2019/07/09 16:34:09 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0 2019/07/09 16:34:10 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0 2019/07/09 16:34:11 [INFO] dbSyncer[0] sync: +forwardCommands=0 +filterCommands=0 +writeBytes=0
其中forwardCommands表示發送的命令個數,filterCommands表示過濾的命令個數,好比opinfo或者指定了filter都會被過濾,writeBytes表示發送的字節數。
數據校驗工具
redis-full-check經過全量對比源端和目的端的redis中的數據的方式來進行數據校驗。
校驗執行命令
./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
查看比對結果
查看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.3 SQLite version 3.7.17 2013-05-20 00:56:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .tables FINAL_RESULT field key sqlite> select * from key; 1|single23|string|lack_target|0|2|0 2|test|string|lack_target|1|4|0 3|single2|string|value|9|1|9
信息列對應關係: id, key, type, conflict_type, db, source_len, target_len
本文由mirson創做分享,如需進一步交流,請加QQ羣:19310171或訪問www.softart.cn