Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

多次使用redisk-shake进行同步时,list类型的值会被append而不是rewrite #921

Open
hevel opened this issue Jan 21, 2025 · 20 comments

Comments

@hevel
Copy link

hevel commented Jan 21, 2025

如题,这个rewrite https://github.com/tair-opensource/RedisShake/blob/v4/internal/rdb/rdb.go#L205 方法,刚redis的类型为list时,会不是rewrite的行为,而是append

@suxb201
Copy link
Member

suxb201 commented Jan 24, 2025

你要区分 list 类型的 key 是在 rdb 中还是 aof 中。在 aof 中的话只能是 append。
如果你想永远是 rewrite 可以考虑 ScanReader

@lvxiaorun
Copy link

lvxiaorun commented Feb 27, 2025

当使用sync_reader和redis_writer的时候,有一个list结构
源库A lpush test 1
目标库B lpush test 2
同步之前不执行flushall
开始同步:
rdb同步完成后:
在B库执行 lrange test 0 10
期望的结果1
实际结果2 1
这种情况只能通过同步前flushall解决吗

@suxb201
Copy link
Member

suxb201 commented Feb 27, 2025

@lvxiaorun 不合预期,可能操作出问题了。

@lvxiaorun
Copy link

lvxiaorun commented Feb 27, 2025

@lvxiaorun 不合预期,可能操作出问题了。
不好意思 前面打错了,实际结果是 2 1
但是我预期是直接完成整个key的替换

@suxb201
Copy link
Member

suxb201 commented Feb 27, 2025

不合预期,期望结果 1,默认配置下会报错才对。

@lvxiaorun
Copy link

你说这个参数吗
RDBRestoreCommandBehavior
我看是scan模式下才会用到
sync_reader并没有

@suxb201
Copy link
Member

suxb201 commented Feb 27, 2025

都会用到 RDBRestoreCommandBehavior

@lvxiaorun
Copy link

lvxiaorun commented Feb 27, 2025

我是基于这个提交的代码看的
0a7aad7
看起来是最新的

@suxb201
Copy link
Member

suxb201 commented Feb 27, 2025

你全局搜下 redis_standalone_writer.go 中也用到了

@suxb201
Copy link
Member

suxb201 commented Feb 27, 2025

额,被这个 PR 改掉了:9527b04#diff-72fe41df5b33ac373ada8ec95dd77a10763f67cdad644c8e4f07be47c225edd5L160
确实现在不会覆盖

@lvxiaorun
Copy link

是的 这个我之前就看到了
但是这个其实是在执行restore的时候报错才会走到这里
然后我前面的场景应该是,redis-shake直接把rdb里面的内容变成 rpush test 1 发到目标库了
并没有对整个key进行 restore,所以结果是2 1

你全局搜下 redis_standalone_writer.go 中也用到了

@lvxiaorun
Copy link

额,被这个 PR 改掉了:9527b04#diff-72fe41df5b33ac373ada8ec95dd77a10763f67cdad644c8e4f07be47c225edd5L160 确实现在不会覆盖

嗯 明白了 感谢

@lvxiaorun
Copy link

lvxiaorun commented Feb 27, 2025

看了一下这个PR,结合当前代码,针对类似于list、hash、zset等类型,我想在Rewrite之前,在Entry管道里面放入删除整个key的命令,以保证跟这个PR之前的行为一致,请教你一下这个的合理性以及可行性 @suxb201

@suxb201
Copy link
Member

suxb201 commented Feb 28, 2025

@lvxiaorun 其实可以直接 restore 命令带上 rewrite 参数,也就是回滚那个 PR 的内容。我不记得当时为啥去掉 restore 逻辑了。

@lvxiaorun
Copy link

@lvxiaorun 其实可以直接 restore 命令带上 rewrite 参数,也就是回滚那个 PR 的内容。我不记得当时为啥去掉 restore 逻辑了。

嗯 我前面的想法就是想保留这个PR的内容,因为这个看起来针对对一些大对象,还是可以节省不少内存占用的

@suxb201
Copy link
Member

suxb201 commented Feb 28, 2025

那 del 也合理的,受 RDBRestoreCommandBehavior 参数控制好了,如果是 rewrite 就额外发一个 del

@lvxiaorun
Copy link

嗯 感谢 我尝试写一个PR

@lvxiaorun
Copy link

我在list的Rewrite方法里面加上了这一行
o.cmdC <- RedisCmd{"del", o.key}
然后代码如下:

func (o *ListObject) Rewrite() <-chan RedisCmd {
	go func() {
		defer close(o.cmdC)
		o.cmdC <- RedisCmd{"del", o.key}
		switch o.typeByte {
		case rdbTypeList:
			o.readList()
		case rdbTypeListZiplist:
			o.readZipList()
		case rdbTypeListQuicklist:
			o.readQuickList()
		case rdbTypeListQuicklist2:
			o.readQuickList2()
		default:
			log.Panicf("unknown list type %d", o.typeByte)
		}
	}()
	return o.cmdC
}

基于我之前的场景测试了一下结果符合预期

然后我打算在types下面的除了string类型的其他类型(包括hash、list、mobbloom、set、stream、tairhash、tairzset、zset)都这么操作,会带来其他问题吗?
@suxb201

@suxb201
Copy link
Member

suxb201 commented Mar 3, 2025

@lvxiaorun 应该没问题

@lvxiaorun
Copy link

@lvxiaorun 应该没问题

有空看下我的RP,感谢 @suxb201

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants