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

太长不看:

  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 报错。

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

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

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

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

  • 思源笔记

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

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

    22340 引用 • 89392 回帖 • 1 关注

相关帖子

优质回帖
  • tianzhongs 1 赞同

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

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

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

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

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

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

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

    image.png

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 所以你是觉得这样就算结构化了嘛。那这个要求和难度都不算太高,改善也不大就是了。这个实现无论是轮询还是系统监听都能做到,但是还是如上面所说,这方面再怎么改善也是提高了在快照上传到云端前的快照建立速度,但无论什么情况下,基本快照建立都不是主要时间。oss 的并发上传限制、思源保守的云端锁、快照分片数量、本地索引校验机制,无论哪一个的改善都远远比这个显著。

    我个人觉得恰恰相反,这个不是为了减少本来就不慢的建立快照的时间,而可以解决我同步的时候,我直接知道我应该同步哪几个文件,而不用还要携带本来就应该是中间件写入储存器之前,供中间件自己建立同步流程用的零零碎碎的小文件,以及可以在让客户端拿到数据时尽量目标明确的去校验特定的文件

    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 基本上完全一个原理,但是官方同步,如果只是一个频繁地备份,我觉得至少不能作为一个优势,不说是缺点已经很不错了

  • sunk926 1 评论
    #!/bin/sh
    docker stop siyuan 
    
    echo -e "\n\n" >> /root/siyuan/rsync.log
    echo Sync started at $(date "+%Y-%m-%d %H:%M:%S")  >> /root/siyuan/rsync.log
    mount -t cifs -o username=sun,password=123456 //192.168.8.8/f/ /mnt/windows_share
    
    #rsync -avz --delete --exclude=rsync.log /root/siyuan/ /mnt/windows_share/siyuan >> /root/siyuan/rsync.log 2>&1 || /usr/bin/pwsh /root/siyuan/qqMail.ps siyuanSyncError_192.168.8.8
    
    rsync -avz --delete --exclude=rsync.log /root/siyuan/ /mnt/windows_share/siyuan || /usr/bin/pwsh /root/siyuan/qqMail.ps siyuanSyncError_192.168.8.6
    
    umount /mnt/windows_share
    docker start siyuan
    

    这是我之前的 linux 上的同步方案,你可以参考一下,每天晚上自动停止思源服务,自动挂载备份,然后同步,同步出错后发送邮件通知, 还有失败日志. 用了好几年了,几乎没出过问题,就算磁盘满 发过几次邮件.你可以修改一下在桌面端使用,原理一样的.

    其实现在用的少了,之前还自己搭建 s3,太折腾了,目前就用 cloudflare 了,省事,反正你只要不要往笔记里面塞太多大文件,同步还是能接受的.
    sunk926
  • 查看全部回帖

推荐标签 标签

  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖 • 8 关注
  • CSDN

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

    14 引用 • 155 回帖
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 552 关注
  • abitmean

    有点意思就行了

    29 关注
  • 导航

    各种网址链接、内容导航。

    40 引用 • 173 回帖
  • CloudFoundry

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

    5 引用 • 18 回帖 • 167 关注
  • 机器学习

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

    83 引用 • 37 回帖
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 618 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 477 关注
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 724 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 114 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 51 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • CAP

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

    11 引用 • 5 回帖 • 607 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3453 回帖 • 203 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 463 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 672 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 3 关注
  • LeetCode

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

    209 引用 • 72 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 71 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 633 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 681 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖