S3 双端同步文件丢失的问题(必现)

本贴最后更新于 255 天前,其中的信息可能已经斗转星移

本人程序猿一枚,最近想找一个趁手的笔记软件,尝试了 Obsidian、Joplin、logseq、为知笔记,但是最喜欢的还是思源笔记,感觉编辑器用起来特别顺手,UI 界面也很是清爽,很多细节都让我深深地感觉到了作者的深思熟虑和工匠精神。遂充值了早鸟,以表敬意。

因为我这边需要在多个客户端间进行数据同步,所以在 NAS 上搭建了 S3,主要是用 PC 为主,偶尔也会用手机写点东西。

单机与服务器同步时很稳定。**但是今天让我吓了一跳,我在 PC 上写了很多笔记,做了很多更改,晚点时间又手机选择“上传本地数据快照”同步后,发现今天在 PC 上写的东西全都不见了,不由得心中一惊,感觉要出事。后来凭着自己多年写代码的经验终于从数据快照中恢复了丢失的笔记。**也幸亏我是能折腾的,换普通人可能都懵了。

因为怕后面又出现丢数据的问题,今晚我专门重现了这个必现的文件丢失问题,现描述如下。

软件基本设定

  • 一台 PC 和 一部手机,S3 服务器;
  • PC 设置为自动同步,手机设置为完全手动同步;
  • 保证当前 PC 和 手机 的内容都一致;

重现步骤

  1. 在 PC 端新建一个笔记;
  2. 点击 PC 上的同步按钮强制同步一次;
  3. 关闭 PC 上的思源笔记;
  4. 打开手机端的思源笔记;
  5. 点击手机上的“同步”按钮,在弹出菜单上选择“上传本地数据快照”;
  6. 退出手机端思源笔记;
  7. 重新打开 PC 上的思源笔记,并点击“同步”按钮;
  8. 发现 PC 端上刚才新建的笔记消失了;

问题猜测

对于此问题,我猜测原因是:手机端在执行“上传本地数据快照”时,用自己的快照强制覆盖了服务器端的快照版本。

问题的危害

经常有如下的工作场景:

在 PC 端写了很多的文档,然后正常同步给了服务器。后面手机端打开时,由于选择的是手动同步方式,可能版本已经落后于服务端了,但此时又在手机上写了另外一个文档,习惯性地就点击“上传本地数据快照”,结果手机的文档上传了,但 PC 之前上传的文档就全丢了。

如果当时能发现丢文件了,还可以通过快照恢复回来。但就怕当时没发现丢文件,过了很久才发现自己写的东西找不到了,到时再回去找快照恐怕连几月几日写的都记不清了。

另外,对于非程序员出身的普通用户,当发生数据丢失时,其实是很被动的,虽然可以找论坛、找教程去恢复数据,虽然 D 大也一直强调数据不会丢,但对用户的体验真的很不利,尤其是对不喜欢折腾的,只是想安安心心写笔记的用户。

请求改善的理由

我也在论坛上搜索过相关的问题,D 大也回复说,尽量避免两边版本不一致就进行同步的问题。但是以我多年程序开发的经验,我感觉这里还是有可以改进的地方。

比如,我们常用的版本管理软件 SVN,服务器允许 N 个客户端与同一个服务器进行代码同步,这 N 个客户端可能处于完全不同的 Revision,每个客户端都独立地在本机上,基于各自不同的 Revision 上进行 Add、Modifiy、Delete 的文件操作,随后每个客户端都可以在任意时间,自由的提交自己的改动到服务器,服务器并不会因为 A 客户端提交了代码,就把 B 客户端之前提交的代码给弄丢掉。当然此时我们假设 A、B 不是在操作同一个文件。

回到本问题,虽然我对思源笔记的同步原理还不太清楚,不过我认为每次同步,应该是同步客户端快照之间的 Delta Changes,而不该是直接拿客户端的快照去覆盖服务器端的快照。

如果我上面说的有错误,也望海涵,毕竟我也才刚开始接触思源笔记 😄。

最后再啰嗦两句

我想,选择思源笔记的用户大都视“数据安全、数据稳定”为第一位的。

真心希望思源能够在稳定性上再让用户吃颗定心丸,让更多用户“用爱发电”~~~

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18829 引用 • 70486 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • zxhd86 1 赞同

    据我所知,上传本地数据快照是完全手动同步的选项,这个功能的意思就是以本地快照覆盖云端。一般的同步使用手动同步和自动同步足以。

    1 回复
  • 建议先看下帮助文档,你这个操作就是文档里明确说的冲突的问题,手机端使用时,没有点下载全部,既然无法保证每次使用前下载云端保持云端一致,我建议使用自动同步。

    1 回复
  • i1356

    行文风格与逻辑条理,一看就是程序员。

  • seeingrain

    针对“手动同步”这个功能,按照上面的重现步骤,无论哪种操作都不可行:

    • 如果先点“上传”,则会覆盖其他端之前上传的内容;
    • 如果先点“下载”,手机上本地新增的内容会变成“Conflict”;

    左右为难,有些尴尬 😂

    所以,就事论事,可以认为“手动同步”这个功能目前可用条件较为严苛。

    1 回复
  • 这个功能的用法就是对一些网络差需要离线使用的人提供的。。不想每次打开就同步。

    按照目前对比快照的同步实现方式和操作,不管是自动、半自动、完全手动,都是需要先同步一致再新增编辑,对于同一个文件的多端编辑并不存在合并的操作。

    私以为,“手动同步”的开发初衷是:当手机没条件连接到服务器时,但突然有脑袋灵光一现的闪念需要快速记录时,可以在手机上迅速本地添加内容,等后面有条件联网时,再同步到云端。 但是此功能目前适用条件较为严苛,甚至可以被视为一个危险操作:必须保证手机 当前快照版本 到 Now 的这段时间,PC 无任何上传。否则不是数据被覆盖就是产生同步冲突(见我上一个回复)。
    seeingrain
    @seeingrain 那可能理解错了。本身思源就是本地离线的,对于没网的情况,用哪种同步都是一样的,同步只是为了多设备使用一样的数据。另外就是,不是对同一个文件编辑一般不会冲突,比如如果手机编辑了当天日记,没上传,电脑又编辑了当天日记,上传,那对应的这个当天日记文档就会冲突,根据文件手工复制合并即可。
    mozhu
    @ciwoyipang 我认为多端协同离线编辑,应该算作“具备同步功能的笔记软件”的刚需。而且此问题无论是理论上还是实践上都是可行的,典型的行业软件就是程序员每天都用的 SVN,每个程序员都是离线的写代码,然后联网提交代码。只要不是修改同一个文件的同一行代码,都不会产生谁覆盖谁代码的问题。
    seeingrain
  • seeingrain

    私以为,“手动同步”的开发初衷是:当手机没条件连接到服务器时,但突然有脑袋灵光一现的闪念需要快速记录时,可以在手机上迅速本地添加内容,等后面有条件联网时,再同步到云端。

    但是此功能目前适用条件较为严苛,甚至可以被视为一个危险操作:必须保证手机 当前快照版本 到 Now 的这段时间,PC 无任何上传。否则不是数据被覆盖就是产生同步冲突(见我上一个回复)。

  • seeingrain

    更新

    刚才又测试了“自动同步”方案,PC 端和 手机端 都本地新增了一些文档,然后点击“同步”按钮,并未发现文档丢失的问题。

    所以,目前的问题点集中在“手动同步”这个功能点存在严重的安全隐患和不可用性上。

  • zxhd86 1 评论

    当手机没条件连接到服务器时,但突然有脑袋灵光一现的闪念需要快速记录时,可以在手机上迅速本地添加内容,等后面有条件联网时,再同步到云端。

    据我所知,不是,因为思源的同步机制是基于快照的,完全手动同步的意义就是自己处理快照,放弃思源自身的快照合并机制。

    这实际上是在之前一个移动端 bug 导致的权宜选项,因为部分移动端平台的时间戳无法精确到毫秒(如华为),导致与 pc 端不一致,进而会导致同步的时候出现大量冲突和重新上传,所有才有这个选项。目前已经放弃了毫秒级别的时间戳,所以这个 bug 已消除。因此,目前完全手动上传的意义就是覆盖上传,在一定情况下能修复损坏的云端快照。

    嗯,目前看起来,“手动同步”应该不是一个日常同步的功能,而是一个特殊的云端故障后的修复功能。估计后面会有不少用户会踩到这颗雷。
    seeingrain 1 赞同
  • seeingrain 2 赞同

    碎碎念

    虽然帮助文档很重要,但是不能指望每个用户都完全认真的读完帮助文档。

    就像我一枚程序员,本职工作就必须阅读大量文档,从 20 年前的 MSDN,到行业内的英文 Paper。但我依然不认同“一个普通用户应该读完所有的帮助文档才开始使用工具”这件事情,一个好用的工具应该是“易用的”、“鲁棒的”。

    “手动同步”这颗雷既然开放出来给普通用户用,那么就应该至少是“安全的”,否则应慎重开放给普通用户。

  • zxhd86 1 评论

    另外,svn 是一个中心式系统,而思源的同步机制是做了一致性牺牲、并添加了端到端加密的分布式系统,两者在一致性上是不等同的,思源只能在符合条件的情况下做到最终一致性,但也换来了更高的性能、更低的自托管需求。

    SVN 也不过是一个团队协同互相同步代码的中间桥梁而已,程序员写代码时也是离线的写代码,上传到 SVN 服务器也不过是为了让其他程序猿同步到他的最新内容而已。而端到端对称加密完全可以在客户端本地做一致性检查,也就是说客户端有权认为云端数据是非法的。
    seeingrain
  • 但是,互相同步代码这一步就已经有区别了,分布式和中心式就是不一样的……

    在 svn 上,只有中心服务器有完整的版本,一旦 svn 中心服务器爆炸,就没有历史版本了。而且,svn 需要一个云端运行的服务器。

    在思源上,所有设备都有自己的一套版本,云端拥有你上传的全部版本。

    那么在笔记软件中,离线查看版本是不是刚需?低成本、不需要可运行服务器的托管方案是不是更需要?

    所有思源才是这个样子。

    另外,我不是很能理解本地一致性检查是什么意思,它能解决什么问题。

    1 回复
  • 另外,

    多端协同离线编辑,应该算作“具备同步功能的笔记软件”的刚需。

    我深表认同,但是

    而且此问题无论是理论上还是实践上都是可行的

    这一点我就不能认同了。中心式系统可以通过对于中心式系统的提交方案来解决冲突,也就是强制每一端都要在提交前先获得中心服务器的最新情况,合并完冲突再提交,但是在分布式系统中是不成立的。关于这点,可以看看 CAP 理论。

  • seeingrain

    对不起,我觉得 git 可能比 SVN 更恰当些。git 库是可以做到每个人自己在硬盘上开个 repository,自己离线提交到自己的库里面的。而 Git 服务器无非是解决了两个需求:团队代码协同 和 代码备份(防止自己硬盘爆炸)。类比到思源笔记来说,就是 多客户端离线编辑并同步 和 笔记备份(防止电脑硬盘爆炸)。

    当然,我不是说我们就要做到 git 那么强大,至少是有思路可以借鉴的。而 Git 的思路,也满足你上面提到的:自托管、离线查看、低成本、不强制服务器、可以接受的性能,最重要的是,能满足各端不分前后顺序的同步。

    1 回复
    1 操作
    seeingrain 在 2023-08-23 13:19:41 更新了该回帖
  • 对,git 是更好的比喻,实际上,思源的同步机制跟 git 更像,但除了端到端加密外,还有一个显著的差异:思源的同步默认是只拉取最新的分支,而给 git 必须把历史版本都拉下来。

    而且,git 处理冲突跟思源没什么太大区别,提交到云端时,git 需要先 pull 拉取,本地合并冲突再 push 到云端,思源的自动同步和手动同步只是把这些步骤合并了。

    思源的完全手动同步类似于 git 的 git push --force,在结果上是一致的。

    1 回复
  • seeingrain 2 评论

    了解,那既然有做到 先 pull 再 push,为何不将 “完全手动同步”功能也做成 手动触发的“先 pull 后 push”的机制?而把现在当前的上传/下载作为数据库崩溃时的修复按钮?

    1 回复
    这同样是我不解的地方,我也在试图让开发者提供一个不需要开启时自动同步、能够自动处理合并的同步模式,但官方没有接受。
    zxhd86 1 赞同
    @zxhd86 那我们达成共识了,希望官方能做一个“开启时不同步,但使用过程中随时可以手动点同步按钮”的功能,支持 先 pull 后 push 的流程,而不是拿客户端或服务端的快照强制覆盖对端。
    seeingrain
  • MkFly 1 评论

    了解,那既然有做到 先 pull 再 push,为何不将 “完全手动同步”功能也做成 手动触发的“先 pull 后 push”的机制?而把现在当前的上传/下载作为数据库崩溃时的修复按钮?

    这是为了应对云端快照出现损坏,而本地没问题的情况。

    手动就已经够你说的功能了

    目前的手动同步模式非常危险,一不小心会丢数据的。
    seeingrain
  • programfan 1 赞同 3 评论

    回想一下 git 如何解决同一个文件两处不同修改产生的合并冲突,就可以理解这个「同步」为什么这么难搞了。简单来说,git 对这种冲突得留给用户手动解决,如果要同时保留双方的修改,必须得是文本文件。但思源的同步对象是加密后的二进制块,没有文本文件可用,就只能回退到本地和远端版本二选一的情况,不符合用户期望并丢失数据是一定会发生的事情。除非回到明文文本存储,这个问题我觉得技术上无解。

    同步这个功能要保证不出问题,还得依靠把自己的工作流「线性化」,同一时间只在一个设备上更新笔记,并且打开自动同步功能,保证每一个更新都及时同步到远端。当然如果更新频次低,手动同步并保证「启动笔记后同步一次,关闭笔记前同步一次」,也不会出问题。

    如果需要多端同时修改,这个需求技术上其实等价于多人协作,目前可行的方法是把 data 目录用 git 管起来,然后多端通过 git 同步和解决冲突。思源最开始的时候就是使用的这种方式。

    你说到处理冲突问题,其实都是我们程序员的日常工作。我觉得绝大部分情况都是不存在文件冲突的,如果出现冲突,git 会有两份,.local 和 .remote,选哪一个由客户端做决定。 而我们现在碰到的是,他有些文件直接没了,这一点挺危险的。
    seeingrain
    靠用户“自律”实现工作流线性化,只是一个 Work Around,权宜之计了,现在也只能这么将就下了。
    seeingrain
    用 git 管理 data 文件夹这个想法还是挺天才的,只可惜手机端无法用起来,可惜了。
    seeingrain
请输入回帖内容 ...