tair-opensource / RedisShake

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

如果网络连接断开,会panic #601

Open zhanghaiyang9999 opened 1 year ago

zhanghaiyang9999 commented 1 year ago

问题描述

在同步过程中,如果目标redis网络断开,redisshake会panic。

redis-shake 的日志: BytesCount=[0]bytes, diff=[0], aofReceivedOffset=[532], aofAppliedOffset=[532] 2023-05-05 17:23:13 INF syncing aof. allowOps=[0.20], disallowOps=[0.00], entryId=[14], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[546], aofAppliedOffset=[546] 2023-05-05 17:23:18 INF syncing aof. allowOps=[0.00], disallowOps=[0.00], entryId=[14], InQueueEntriesCount=[0], unansweredBytesCount=[0]bytes, diff=[0], aofReceivedOffset=[546], aofAppliedOffset=[546] 2023-05-05 17:23:19 2023-05-05 17:23:19INF goroutine 34 [running]: [runtime/debug.Stack()]<-runtime/debug/stack.go:24 +0x65 [github.com/alibaba/RedisShake/internal/log.Panicf({0x131cca1, 0x45}, {0xc0000bdf78, 0x4, 0x4})]<-github.com/alibaba/RedisShake/internal/log/func.go:27 +0x36 [github.com/alibaba/RedisShake/internal/writer.(redisWriter).flushInterval(0xc000184980)]<-github.com/alibaba/RedisShake/internal/writer/redis.go:75 +0x3b4 [created by github.com/alibaba/RedisShake/internal/writer.NewRedisWriter]<-github.com/alibaba/RedisShake/internal/writer/redis.go:35 +0x197 [ INF goroutine 1 [running]: [runtime/debug.Stack()]<-runtime/debug/stack.go:24 +0x65 [github.com/alibaba/RedisShake/internal/log.Panicf({0xc00018a180, 0x76}, {0x0, 0x0, 0x0})]<-github.com/alibaba/RedisShake/internal/log/func.go:27 +0x36 [github.com/alibaba/RedisShake/internal/log.PanicError({0x13a1380?, 0xc00004a0a0?})]<-github.com/alibaba/RedisShake/internal/log/func.go:36 +0x33 [github.com/alibaba/RedisShake/internal/client.(Redis).flush(0xc0001849c0?)]<-github.com/alibaba/RedisShake/internal/client/redis.go:100 +0x2a [github.com/alibaba/RedisShake/internal/client.(Redis).SendBytes(0xc000104a80, {0xc002212000?, 0xc0000863c0?, 0xc00009c2d0?})]<-github.com/alibaba/RedisShake/internal/client/redis.go:94 +0x45 [github.com/alibaba/RedisShake/internal/writer.(redisWriter).Write(0xc000184980, 0xc00005e000)]<-github.com/alibaba/RedisShake/internal/writer/redis.go:54 +0x12d [main.main()]<-github.com/alibaba/RedisShake/cmd/redis-shake/main.go:109 +0x7da [ 2023-05-05 17:23:19 PNC2023-05-05 17:23:19 redisWriter received error. error=[read tcp 10.20.50.75:50757->10.20.50.80:6379: wsarecv: An existing connection was forcibly closed by the remote host.], argv=[PING], slots=[], reply=[] panic: redisWriter received error. error=[read tcp 10.20.50.75:50757->10.20.50.80:6379: wsarecv: An existing connection was forcibly closed by the remote host.], argv=[PING], slots=[], reply=[]

goroutine 34 [running]: github.com/rs/zerolog.(Logger).Panic.func1({0xc00009a540?, 0x0?}) github.com/rs/zerolog@v1.28.0/log.go:375 +0x2d github.com/rs/zerolog.(Event).msg(0xc000048180, {0xc00009a540, 0xbf}) github.com/rs/zerolog@v1.28.0/event.go:156 +0x2a5 github.com/rs/zerolog.(Event).Msgf(0xc000048180, {0x131cca1?, 0x21e?}, {0xc00023df78?, 0x1302f84?, 0x3?}) github.com/rs/zerolog@v1.28.0/event.go:129 +0x4e github.com/alibaba/RedisShake/internal/log.Panicf({0x131cca1, 0x45}, {0xc00023df78, 0x4, 0x4}) github.com/alibaba/RedisShake/internal/log/func.go:32 +0xef github.com/alibaba/RedisShake/internal/writer.(redisWriter).flushInterval(0xc000184980) github.com/alibaba/RedisShake/internal/writer/redis.go:75 +0x3b4 created by github.com/alibaba/RedisShake/internal/writer.NewRedisWriter github.com/alibaba/RedisShake/internal/writer/redis.go:35 +0x197 源端 Redis 版本:5.0.14,redis官方版本 日志:

日志贴在这里

目的端 Redis 版本:5.0.14,redis官方版本 日志:

日志贴在这里

image

suxb201 commented 1 year ago

符合预期

zhanghaiyang9999 commented 1 year ago

请教一下,为什么会是这个设计行为?而不是比如自动重连?

符合预期

请教一下,为什么会是这个设计行为?而不是比如自动重连等?

suxb201 commented 1 year ago

@zhanghaiyang9999 Shake 不知道已经发送的但是还没回复的命令是在发送途中,还是对端已经执行但是还没回复。所以不敢随便重试。

zhanghaiyang9999 commented 1 year ago

@zhanghaiyang9999 Shake 不知道已经发送的但是还没回复的命令是在发送途中,还是对端已经执行但是还没回复。所以不敢随便重试。

我看介绍说有断点续传功能,那个断点续传指的不是网络断开的这种情况吗?还是在最新版本中把这个功能去掉了? 另外,如果是使用覆盖模式,重连以后,就算对端已经执行了一些命令,多传一些key数据过去,应该也没有关系吧?不知道这个理解是否正确?谢谢!

suxb201 commented 1 year ago

@zhanghaiyang9999

  1. 没有覆盖模式,不是所有命令都是幂等的
  2. 请问哪看的断点续传文档,我去删掉
zhanghaiyang9999 commented 1 year ago

@zhanghaiyang9999

  1. 没有覆盖模式,不是所有命令都是幂等的
  2. 请问哪看的断点续传文档,我去删掉 这么好的功能,不要删掉啊!

https://developer.aliyun.com/article/783138?spm=a2c6h.14164896.0.0.2a263568aCusYF

image

baronwangr commented 1 year ago

shake是用来做一次性数据迁移和导入的,其设计目的不是长期的同步链路。redis的psync协议的续传能力非常有限,没有后续定制的features。 谢谢支持

zhanghaiyang9999 commented 1 year ago

shake是用来做一次性数据迁移和导入的,其设计目的不是长期的同步链路。redis的psync协议的续传能力非常有限,没有后续定制的features。 谢谢支持

多谢! 如果要支持网络断开重连后,进行续传的功能,目前主要的难点或者主要问题大概是什么?是在全量同步阶段还是在增量复制阶段,还是两个阶段都有不同的问题所在?如果了解得比较详细的话(包括问题、局限性等),我愿意加入redisshake的开发与维护,可以作为下一个版本的一个feature,不知道是否可以?多谢!

suxb201 commented 1 year ago

@zhanghaiyang9999 参考:https://github.com/tair-opensource/RedisShake/discussions/494

zhanghaiyang9999 commented 1 year ago

@zhanghaiyang9999 参考:#494 多谢! 这个上面提到的redisshake https://developer.aliyun.com/article/783138 和本项目redisshake不是同一个吗?

baronwangr commented 1 year ago

shake是用来做一次性数据迁移和导入的,其设计目的不是长期的同步链路。redis的psync协议的续传能力非常有限,没有后续定制的features。 谢谢支持

多谢! 如果要支持网络断开重连后,进行续传的功能,目前主要的难点或者主要问题大概是什么?是在全量同步阶段还是在增量复制阶段,还是两个阶段都有不同的问题所在?如果了解得比较详细的话(包括问题、局限性等),我愿意加入redisshake的开发与维护,可以作为下一个版本的一个feature,不知道是否可以?多谢!

一如既往欢迎PR和参与建设! shake兼容的是sync协议,如果可以完整的支持psync2是可以在一定程度上,支持有限的断点续传的。原理主要可以了解下redis的replication buffer的配置。一旦超出这个环形缓冲区,那么就必须走全量复制。又由于redis的命令不是幂等的(比如list都会被rewrite成rpush)所以数据会出现大量错误。

不能稳定同步不是工具的错,而是redis自身psync协议设计的问题

image

zhanghaiyang9999 commented 1 year ago

shake是用来做一次性数据迁移和导入的,其设计目的不是长期的同步链路。redis的psync协议的续传能力非常有限,没有后续定制的features。 谢谢支持

多谢! 如果要支持网络断开重连后,进行续传的功能,目前主要的难点或者主要问题大概是什么?是在全量同步阶段还是在增量复制阶段,还是两个阶段都有不同的问题所在?如果了解得比较详细的话(包括问题、局限性等),我愿意加入redisshake的开发与维护,可以作为下一个版本的一个feature,不知道是否可以?多谢!

一如既往欢迎PR和参与建设! shake兼容的是sync协议,如果可以完整的支持psync2是可以在一定程度上,支持有限的断点续传的。原理主要可以了解下redis的replication buffer的配置。一旦超出这个环形缓冲区,那么就必须走全量复制。又由于redis的命令不是幂等的(比如list都会被rewrite成rpush)所以数据会出现大量错误。

不能稳定同步不是工具的错,而是redis自身psync协议设计的问题

image

多谢! 这里说的断点续传指的是在满足一定条件下的有限断点续传,不是要求任意情况下的断点续传,当不能满足断点续传的要求时就不需要断点续传,就进行全量同步,这是合理的。比如replication buffer满了,就进行全量同步,这是可以接受的,如果有希望能够处理长一些的时间断开,则他可以把redis的buffer设置大一些。但是如果哪怕仅仅断开网络一秒,而且replication buffer也没有满,也要求全量同步并要求程序panic并重启,可能这并不是一个最好的解决方案。

baronwangr commented 1 year ago

image

baronwangr commented 1 year ago

shake是用来做一次性数据迁移和导入的,其设计目的不是长期的同步链路。redis的psync协议的续传能力非常有限,没有后续定制的features。 谢谢支持

多谢! 如果要支持网络断开重连后,进行续传的功能,目前主要的难点或者主要问题大概是什么?是在全量同步阶段还是在增量复制阶段,还是两个阶段都有不同的问题所在?如果了解得比较详细的话(包括问题、局限性等),我愿意加入redisshake的开发与维护,可以作为下一个版本的一个feature,不知道是否可以?多谢!

一如既往欢迎PR和参与建设! shake兼容的是sync协议,如果可以完整的支持psync2是可以在一定程度上,支持有限的断点续传的。原理主要可以了解下redis的replication buffer的配置。一旦超出这个环形缓冲区,那么就必须走全量复制。又由于redis的命令不是幂等的(比如list都会被rewrite成rpush)所以数据会出现大量错误。 不能稳定同步不是工具的错,而是redis自身psync协议设计的问题 image

多谢! 这里说的断点续传指的是在满足一定条件下的有限断点续传,不是要求任意情况下的断点续传,当不能满足断点续传的要求时就不需要断点续传,就进行全量同步,这是合理的。比如replication buffer满了,就进行全量同步,这是可以接受的,如果有希望能够处理长一些的时间断开,则他可以把redis的buffer设置大一些。但是如果哪怕仅仅断开网络一秒,而且replication buffer也没有满,也要求全量同步并要求程序panic并重启,可能这并不是一个最好的解决方案。

welcome PR!

zhanghaiyang9999 commented 1 year ago

image

感谢! 本质上说,我认为psync和binglog是一致的,只是binlog可能会默认存到磁盘上,并且空间很大,和mysql binlog类似。psync只是默认buffer很小,但是这个应该并不会影响他的续传功能,redis的集群应该也是通过psync来复制数据的,应该也是支持断网续传的。

baronwangr commented 1 year ago

redis psync远不到binlog的实现程度。即使搞上去,按redis的写入可能只有几秒的时间。写入量大基本每次都full sync

zhanghaiyang9999 commented 1 year ago

redis psync远不到binlog的实现程度。即使搞上去,按redis的写入可能只有几秒的时间。写入量大基本每次都full sync

是的,不过这是另一个问题,binglog磁盘满了也一样的问题。

baronwangr commented 1 year ago

redis psync远不到binlog的实现程度。即使搞上去,按redis的写入可能只有几秒的时间。写入量大基本每次都full sync

是的,不过这是另一个问题,binglog磁盘满了也一样的问题。

并非抬杠。磁盘满和circular buffer满那简直不能同日而语。redis的psync只有op,没有serverid,没有sequence,没有originator ip,既不能保证幂等,又没法双向保证来源,这东西就是做简单一致性和恢复用的。

拖拉机,不能当成宇宙飞船工作在近月轨道,这就是现实

zhanghaiyang9999 commented 1 year ago

https://developer.aliyun.com/article/783138

多谢!

本项目和 https://developer.aliyun.com/article/783138 中提到的redisshake是同一个项目吗?这个link上面提到了支持续传的方式。不知道是否有参考价值。 多谢!

suxb201 commented 1 year ago

@zhanghaiyang9999 是一个项目,文中是旧版 shake,可以在 v2 分支看到。现在主分支是 v3,去除了原先的断点续传等功能。

zhanghaiyang9999 commented 1 year ago

@zhanghaiyang9999 是一个项目,文中是旧版 shake,可以在 v2 分支看到。现在主分支是 v3,去除了原先的断点续传等功能。

多谢! 有没有v2和v3的feature比较文档,这样可以比较方便确定是使用v2还是v3,多谢!

suxb201 commented 1 year ago

@zhanghaiyang9999 没有比较文档.. 目前只推荐使用 v3,v2 有些未知问题,且不再开发与维护。