Closed
Description
在什么情况下你需要该特性?In what scenarios do you need this feature?
解决文件冲突时的方案
描述可能的最优解决方案 Describe the optimal solution
主要思路来自于git对于文件管理的方式,每次文件同步时,生成对应的md5值,并存下历史的值。形成一条链,每次文件同步时,对比服务与本地的两条链,如果发现冲突,则让用户选择使用本地文件或者服务器文件,服务器保留用户选择的链与文件。
描述候选的解决方案 Describe the candidate solution
No response
其他信息 Other information
No response
Activity
88250 commentedon Jun 3, 2022
手工处理冲突交互上可能比较麻烦。最理想的算法应该是避免产生冲突(比如 CRDT),但是实现上有难度、网络带宽成本较高,性能也不大行。
目前同步算法的主要短板是全库使用一个版本号(data ver)导致粒度不够细致,通过版本号只能决定同步上传和下载方向,方向决定以后就是 file list diff 覆盖,场景举例:
A 设备上修改文件 a 和新增 c 后 data ver 为 5,B 设备上修改文件 b 后 data ver 为 6,云端 data ver 3,。触发 A 同步以后云端数据会被 A data 覆盖(A 和云端一致),然后触发 B 同步以后云端数据再被 B data 覆盖(因为 B data ver 6 大于云端 5,B 和云端一致),这时再次触发 A 同步会进行下载,导致 A 文件 a 的修改被还原为 B 上的 a,新增的 c 被删除。此时这个分布式系统中节点(A、B 和云端)的状态是一致的,都是 data ver 6,虽然满足了一致性,但是这显然不是用户期望的。
用户期望的结果应该是 A 的 a 文件修改和新增 c 文件以及 B 的 b 文件修改能够同步到所有设备上。也就是触发 B 同步时不要直接覆盖云端,而是先 pull 云端变更并进行合并到 B 上,然后再执行上传覆盖云端。
按照这个思路的实现是使用 data ver 决定同步方向的同时在文件列表索引(sync/index.json) 中引入每个文件版本号(file ver),用 ver 可以对比文件粒度的方向,如果要执行 upload 则先 download diff merge;如果要执行 download 则先 upload diff merge。
目前大致就考虑这么多,实现细节上还有待考虑,欢迎讨论。
ssfdust commentedon Jun 3, 2022
端午节快乐,没想到回这么快,大佬今天是在给自己加班吗
版本号的生成方式是根据时间生成的吗,然后diff merge如何处理conflict。
细化版本颗粒度可以解决文件级别的冲突问题,但是内容级别的冲突该如何解决呢?
88250 commentedon Jun 3, 2022
端午快乐。这个算法考虑有一段时间了,但是细节还需要时间验证确认。文件版本号根据修改次数自增,不使用修改时间,否则多设备上的时间同步是个难点。
差异合并(diff merger)只考虑处理文件列表差异,不涉及文件内容差异。也就是说对于相同的文件,还是采用覆盖生成历史的策略。
88250 commentedon Jun 5, 2022
#5093 中将 hash 改用时间对比了,主要是性能问题。实际上多设备上使用时间没有问题,因为下载文件后会调整文件时间,和本地设备实际上关系不大,只要知道变动即可,在大部分时候多设备上刚好修改了又和云端时间一致的概率应该不大,后面如果真出现了再看。
这个 issue 我关闭了,感谢讨论。