关于思源同步为啥这么慢的探究

太长不看:

  1. 扫盘建立快照不够高效,占比 10%
  2. 网络条件拉跨,占比 10-100%(假如你家网速正常就 10%,不正常直接断了,影响算 100% 是没问题吧trollface
  3. 同步有锁,必须交替进行,占比 30%
  4. web 上传对小文件极不友好,占比 50%

关于一些前置的讨论可以看看 Issue #12246 · siyuan-note/siyuan ,我在这里研究了下 obsidian 的 livesync 插件与思源同步机制的差异,试图搞清楚,为啥都能使用 S3 作为同步中介,livesync 可以做到实时同步,而思源则有明显的卡顿感。

一个反直觉的观点是,思源的快照机制并不慢,至少不是同步慢的最主要问题。以下是测试出来的快照建立时间于同步时间之间的差异:

  • 日记编辑 0.75s,未同步
  • 主题更新(22 个文件,2m 数据量)0.86s,同步时间 3s
  • 安装插件(650 个文件,20m 数据量)3.36s,同步时间 94s
  • 删除插件(删除 650 个文件,20mb 数据)0.86s,同步时间 14s

以上都是先建立快照,再进行同步的操作,换而言之,同步的时间已经是去除快照建立的时间了,但是还是可以看出相对于快照操作是很慢的。

因此同步慢的的最大根源就是同步加锁……而已吗?

直到今天之前,我都是这个观点,但我忽然想到,同步加锁只是会影响到另一端同步并下载云端内容的速度,理论上不会影响到我这一端上传的速度,或许还要严格评估一下 web io 对于同步速度的影响。因此我直接在本地搭建了一个 docker minio,新开了一个库作为测试。我同时把我主笔记库的数据复制过来了,总共是 800m 的大小,6500 个文件。

我阅读了 dejavu 的代码,发现它里面有对同时上传文件数的限制。我合理的怀疑这就是问题的根源。于是,我拉到本地,进行修改,将同时上传、下载文件数的限制,也是 NewPoolWithFunc 的 poolSize 全拉高了 10 倍,重新打包思源的 kernel,进行测试。以上所有操作都是基于思源是个开源软件,所有,哎,就是能改着玩!

在我进行修改之前,使用本地的 minio 进行全库上传的耗时是 440s,那么,你觉得我修改后的耗时是多少呢?

还是 436s!

这少掉的 4s,完全可以被认为就是一个误差而已,因此可以说,dejavu 里对同时上传文件大小的限制,根本就不是同步慢的原因。

我尝试绕过思源,直接通过 minio 的 webui 上传,时间相差无几。

接着,我做了另一种尝试,使用 restic 进行备份,然后直接通过 webui 上传。备份同样的内容,思源的同步机制总共生成了 13,062 个文件,259 个文件夹,而 restic 则是 48 个文件,261 个文件夹。

最后,restic 的上传时间为 10s。

在查看日志中发现,minio 的同时上传速度哪怕在本地也只能做到每秒 40 左右的文件。

作为测试,我尝试使用官方的上传机制,这次就更慢了,每秒只能上传 16 个文件。而且甚至因为同时上传等待时间过长,还给我返回了 time out 报错。

因此,问题的根源似乎很清楚了:思源扫盘建立快照当然可以进步,但进步空间不大。改善云端同步协作机制、实现无锁同步,以及改变思源的快照分片机制,才是根本解决方案。

那么,古尔丹,代价是什么呢?

代价就是,从此思源的增量下载能力可能大大减弱,可能你下载一个快照,就得把整个库下载回来,因为现在一个数据分块对应了多个实际的文件,你只能一起下载回来再拆分。

这里,我就不得不感慨,省空间换时间,还是省时间换空间,依然、并且永远,是一个值得考虑的问题啊。

  • 思源笔记

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

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

    22353 引用 • 89453 回帖

相关帖子

优质回帖
  • tianzhongs 1 赞同

    目前的优化的话,我能想到的就是类似于 Duplicati(某备份工具),他也是增量备份,他的逻辑是

    1. 第一个文件:把元数据的一些映射关系做了信息映射;
    2. 别的文件就是加密后的元数据,同样也是进行了分片,但是他多了一个步骤,就是

    压缩,我觉得这个压缩很有搞头

    1. 每次增量备份,只多备份新的修改的元数据对照和压缩的元数据

    他这个备份工具也支持加密,也是一样的,我个人体验同步速度算快的,毕竟他压缩的大小能指定,比如说 650MB(CD 大小),元数据足够大的话,就会有很多的 650MB 的压缩包,上传起来比思源现在的上传小文件肯定会快很多;

    然后就是映射关系,他本地也有一个数据库,保存的是映射关系和日志,相当于是缓存,可以删因为云端也有,这种同步的话,除了第一次同步这个日志数据库慢点,其余时间都比思源快很多。

    加密上传后的的目录:能看到精简了很多

    image.png

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 本地一份全量明文,还有一份大量的分块,空间也没省下来

    1 回复
  • 其他回帖
  • zxhd86

    自己搭建的 minio 吗?个人服务器性能一般都是丐中丐,如果是海外的对象存储

    我不是用个人服务器,我是直接在我自己的电脑上,用 docker 运行 minio,minio 跟思源甚至没经过外网网络交互,全部都是在一台电脑上进行。在 40 并发上传时,minio 的 cpu 占用已经飙升到 40% 了。在我没上传前,它的占用是 0.2%。我觉得 minio 作为这方面最流行的个人 s3 项目,它的代码不至于拉跨商业主流技术好几代,而我给他分配的资源,我个人觉得也应该远胜大部分公有云给你分配的量级。

    你说的外部修改因素我当然是有提及,不然也不会说禁止用户和插件通过思源调用 fs,我的评价是锁都锁了,直接禁止 fs 模块或者其他三方修改,被改了就报错,为什么要承担用户自己外部修改的责任?想要自由度又想要稳定性,哪里来的这么多好事,一切操作最多只通过 api 进行就是最合理的方法,或者直接打乱目录,防止本地有人直接修改本地明文

    如果能这样当然最好,但是确实是有需要放 word,然后外部修改的例子,这方面的应用数不胜数,甚至都需要 D 专门放行,方便内核运行时不会报错,全封了不太对吧……

    你说的只是对比索引然后增量同步而已,我很明确的指出了是只进行同步单个文档的操作,目前就和扫盘然后看一下哪里变了然后同步没什么区别

    因为有上述前提,所以不扫描就是不行的。而且,还是那句话,扫描一遍还真就不花什么时间,它不是制约同步速度的主要因素。

    而 live 并不存在这种情况,虽然没有实时通信的实例,但是它在本地运行了一个可以做到改动与同步同时进行的程序,没错,随着同步和改动一起进行

    我研究过它的代码了,实际上他就是在文件改动的时候动态的把内容加入快照库,然后触发同步,把更新的块打包,和索引一起上传上去。它并没有做所谓的同步操作缓存,至于结构化,我不太理解你的意思。你的意思难道是它会准确的识别操作具体的内容,比如说 md 文本里最后插入了”this is sync“,它就能发送一个{insert:"this is sync"}之类的东西?那你可能要失望了,你可以看看这部分的代码:

    https://github.com/vrtmrz/obsidian-livesync/blob/630889680e6da80a58c55f44ca764eb265758f4c/src/storages/StorageEventManager.ts#L78

    https://github.com/vrtmrz/obsidian-livesync/blob/630889680e6da80a58c55f44ca764eb265758f4c/src/main.ts#L1586

    https://github.com/vrtmrz/obsidian-livesync/blob/630889680e6da80a58c55f44ca764eb265758f4c/src/main.ts#L3092

    https://github.com/vrtmrz/obsidian-livesync/blob/630889680e6da80a58c55f44ca764eb265758f4c/src/storages/SerializedFileAccess.ts#L87

    以上代码的逻辑就是获取文件更改,然后直接视为 string 或二进制,创建快照分片而已,在我的标准里,属实算不上什么结构化。思源要进行这种操作也能做到的,无非就是动态获取修改内容,然后新建指定快照罢了。之前是扫盘获取需要建立快照的文件,现在是你给定路径确定建立快照的文件,区别不大,思源的性能可能还高一点。

    2 回复
  • 第一,我觉得你可能对对象存储有什么误解,对象存储的意义就是为了解决个人服务器带宽或者性能不够,然后提供一种按量计费的套餐,它的带宽是直接和腾讯从三大运营商拉过来的专线对等的,我再说的通俗一点,如果你家里宽带有 10000 兆的带宽,那么你下载腾讯 s3 的速度就是一万兆,你个人就算是硬盘提供得了这么大的速度吗?详情见这里,https://doc.fincloud.tencent.cn/tcloud/Storage/COS/845813/uploaddownloadfaq
    对象存储的性能和带宽不上限,只按量,远超你自己局域网运行一个 docker 的性能

    第二,我说了没有那么好的事情,即自由又稳定,况且,又不是没有解决方案,只需要把附件这种不会频繁变动的内容单独走另一个单独的上传信息通道就好了,而不是放到高频索引里面再扫一遍

    第三,你也看了片段了,可以看到,它不是一个简单的索引触发器,更改的内容是由操作写入的,而不是索引对比文件,索引本身没有问题,问题是只有利用操作来写入索引才能让索引具有足够的时效性,这样做,同步的内容是和操作耦合的,而不是只和扫盘索引耦合,“数据分片”这个概念我也提到了,至少 ob 可以直接知道该同步哪一个 md 文件,思源可以在操作后马上知道该同步哪一个 sy 文件吗?倘若能,为什么要去扫盘?难道是因为我改了一个 sy 文件,每一次都要扫库看看我有没有改其他文件吗?那为什么不一直扫,万一我改了其他的文件但是没该文档,岂不是没有办法了,只能等我改文档的时候再帮我检测一下?这个思路倒是可以理解了。我是真的觉得,和用户的操作一块进行,监听哪些文件发生更改,然后没有中间服务商直接同步哪些文件,都比现在快。

    第四,我知道你不停的强调建立一个快照或者索引有多快,但是,在我用的过程中,建立快照并不是卡我的原因,原因是这个快照索引本身就是没有时效性的,不可靠的,所以它不是建立完就没事了,他需要下载下来,然后解析,然后一个个核对,我的同步大部分时间就是花在这个核对索引上,一直在校验索引,少则校验 5-6s,多则半分钟,3.10 版本有时候校验索引都会卡死,扫盘建立的索引,终究还是要扫盘去核对

    第五,我想表达的意思是,对象存储作为储存器并不是问题,问题是,没有一个很好的《中间件》来作为和对象存储的桥梁,anytype 的中间件,节点原理,即使塞到本体里面一样可以用(它也确实塞进去了),断网后,局域网内客户端是可以互相沟通同步的,每个客户端都具有与储存器之间的完整的中间件,而不是把储存器

    同步应该与实时操作耦合,不然,我只能叫他频繁地扫盘备份,第三方备份这样做完全合理,甚至本应该就这么做,大家为了节省流量,或者因为没有同步感知,都会以较为低频的方式用,和 remotely-safe 基本上完全一个原理,但是官方同步,如果只是一个频繁地备份,我觉得至少不能作为一个优势,不说是缺点已经很不错了

  • tianzhongs

    随便说两点,第一,你拿 ob 的 livesync 实时同步来比较,并不恰当,因为 livesync 的同步是挂在服务器上,其本质就跟你部署在 docker 上,访问网页应用类似;

    当然,这并不是思源同步慢的真正原因,真正的原因是:

    1. 可能存在线程或者文件并行同步的数量限制;
    2. 加密,你应该考虑思源是加密了的,也就是说存在类似于 Cryptomator 那样的加密措施,导致文件和文件夹众多,可以直接在对象存储平台查看加密后的文件夹就会发现非常多image.png
    3. 文件和文件夹的深度和数量都会极其影响同步、复制等速度,这个使用过 npm 以及复制 jar 包的同学应该都深有体会

    我目前每次同步的速度大概在 3s 左右,如果有重大改变,可能会在十几秒左右,但是我觉得这个同步速度其实还好,因为有个 30s 自动同步的机制,所以我平时也很少手动同步,但是每次启动的时候的加载才是让我头痛的,每次都要等待封面,这个有点无语。

    你如果非要对比的话,应该对标是 ob 的 remotely save 插件,记得加上加密,其次,ob 的该插件似乎不会分割文件,所以还是有一定的区别,但是会比你说的 livesync 更接近对比效果。

    如果说解决的话,你要么就不用思源的官方同步,直接用三方同步工具同步 data 文件夹,这个也是可以的,我尝试过,只是不优雅。或者说用 docker 部署,这个优雅,但是只能用浏览器访问。

    1 回复
  • 查看全部回帖

推荐标签 标签

  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 588 回帖
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 67 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖 • 1 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖 • 1 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 168 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 743 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 6 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 510 关注
  • gRpc
    11 引用 • 9 回帖 • 73 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 3 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • 创业

    你比 99% 的人都优秀么?

    84 引用 • 1399 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 762 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    132 引用 • 1114 回帖 • 124 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 9 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 699 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 587 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 453 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 2 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 608 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 164 关注