tair-opensource / RedisShake

RedisShake is a Redis data processing and migration tool.
https://tair-opensource.github.io/RedisShake/
MIT License
3.86k stars 700 forks source link

RedisShake 4.x 初次单机迁移到集群Key丢失以及scan数量与keyspace数量差异问题 #811

Open 52hzbobo opened 6 months ago

52hzbobo commented 6 months ago

问题描述(Issue Description)

单机 redis db:2 ,使用命令: scan 0 count 290000 得到key的条数是: 192700+ redis keyspace数量: 194800+ ( 问题1:与scan到的key数量不一致,待定不是主要问题)


问题2:jar测试代码对比对比集群key: 相差:596条(在集群不存在,这些key有效时间7天) 写了jar包scan对比,丢失的差异key在集群中不存在, 根据源端key过期时间推算差异都在上周五初始开始全量+增量数据时候没有同步到

环境信息(Environment)

日志信息(Logs)

如果有错误日志或其他相关日志,请在这里提供。

If there are any error logs or other relevant logs, please provide them here.

其他信息(Additional Information)

--------------------------------------- 同步的lua脚本 ---------------------------------- function = """ -- 来源库-中台Redis库:172...25 local prefix = nil if DB == 1 then prefix = "C_MID:XX_1:" elseif DB == 2 then prefix = "C_MID:XX_2:" elseif DB == 4 then prefix = "C_MID:XX_4:" elseif DB == 5 then prefix = "C_MID:XX_5:" elseif DB == 7 then prefix = "C_MID:XX_7:"
elseif DB == 8 then prefix = "C_MID:XX_8:"
elseif DB == 9 then prefix = "C_MID:XX_9:"
else -- 其他DB C_MID:DB_N: prefix = "CMID:DB"..DB..":" end

-- 前缀不为空情况下拼接key local ct_n = table.getn(KEY_INDEXES)

-- 前缀不为空情况下拼接key if prefix ~= nil then for i, index in ipairs(KEY_INDEXES) do local key = ARGV[index] ARGV[index] = prefix .. key end end

if ct_n > 1 then shake.log("DB: " .. DB .." | KEY_INDEXES: " .. table.concat(KEY_INDEXES, " ") .. " | ARGV: " .. table.concat(ARGV, " ")) end -- 单机有0~15库,而目标集群只有DB0,func脚本shake.call(DB,..)重写同步会有问题 -- 需在此处重新设置为:0 DB = 0 shake.call(DB, ARGV) """ --------------------------------------- 同步的lua脚本 ----------------------------------

suxb201 commented 6 months ago

问题一:Redis 特性,scan 不保证数量,游标为 0 才表示 scan 完了 问题二:没明白你意思,如果大量 key 带有过期时间的话,dbsize 确实会不一样:https://tair-opensource.github.io/RedisShake/zh/others/consistent.html

52hzbobo commented 6 months ago

scan的游标是为0了,但是主要是[问题2]19w的源端数据同步到集群 存在596条没有成功到目标端redis集群 ,这些数据有效期是604800秒 用java代码对比打印日志:过期时间都是在清除(目标端集群)数据后重新用redisshake进行rdb+aof同步 差异的数据是在重新开始同步的前几个小时内小部分数据 contrasKey:>>> RESOURCES:8fe0f2aa9f4536537325d4655e1e1d3a <-----> expire_time:339983 contrasKey:>>> RESOURCES:29657a29bee3580fd612f3c5eca6a8d9 <-----> expire_time:340314 contrasKey:>>> RESOURCES:7b961a48a2a14b852ef348e3a7331cbe <-----> expire_time:339627 contrasKey:>>> RESOURCES:286e0973863608030e7e3bae63873e2c <-----> expire_time:339829 目标端的集群还未开始正式有服务接入,只是在盘点数据发现差异

suxb201 commented 6 months ago

过期时间都是在清除(目标端集群)数据后重新用redisshake进行rdb+aof同步

没明白意思

52hzbobo commented 6 months ago

简单过程背景说就是:

  1. 在05-24 14:00 清除目标库(集群)
  2. 并RedisShake重新开始跑生产的单机-->目标集群
  3. [sync_reader] sync_rdb = true sync_aof = true
  4. 周一过来观察数据发现差异条数问题,写了jar对比key
  5. 发现596条key没有在集群中,而且丢失的key都是在 05-24 09:00 ~ 05-24 : 14:00左右key
52hzbobo commented 6 months ago

开发和测试由于业务量问题 key 并没有存在差异(运维写py脚本通过keyspace对比) 就是看下 在哪些使用场景会导致key丢失 注:目标集群库并没有业务使用,丢失的key也没有哪些条件下会删除

suxb201 commented 6 months ago

@52hzbobo 我也想不明白,需要你自己想办法查一查了。几个怀疑方向你可以看一下:

  1. 目的端触发了 evict
  2. 数据是周一停止 shake 同步后才刚写入的
  3. 如果 shake 没停,一直在写入,本身同步有延迟可能数据是刚写入源端,还没同步至目的端