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

本贴最后更新于 226 天前,其中的信息可能已经时异事殊

太长不看:

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

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

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

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

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

  • 思源笔记

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

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

    24812 引用 • 102074 回帖

相关帖子

优质回帖
  • tianzhongs 1 赞同

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

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

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

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

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

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

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

    image.png

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 然后就是关于你提供的代码定位,我当然可以跟着你看代码,可以看到,光是监听就写了

    plugin.registerEvent(plugin.app.vault.on("modify", this.watchVaultChange)); plugin.registerEvent(plugin.app.vault.on("delete", this.watchVaultDelete)); plugin.registerEvent(plugin.app.vault.on("rename", this.watchVaultRename)); plugin.registerEvent(plugin.app.vault.on("create", this.watchVaultCreate)); //@ts-ignore : Internal API plugin.registerEvent(plugin.app.vault.on("raw", this.watchVaultRawEvents));

    五个,每一个事件不只是一个触发器来触发进行扫盘索引,而是拥有具体的返回对象,例如

    watchVaultChange(file: TAbstractFile, ctx?: any) { this.appendQueue([{ type: "CHANGED", file }], ctx); }

    通过将文件的修改事件封装成一个对象,这个方法能够为后续的处理提供结构化的数据,这至少是一种基本的处理,至少是和操作挂钩了,返回校验也不需要重新牵一发而动全身

    其他的我就不细看了,要休息

    1 回复
  • 其他回帖
  • 第一,我觉得你可能对对象存储有什么误解,对象存储的意义就是为了解决个人服务器带宽或者性能不够,然后提供一种按量计费的套餐,它的带宽是直接和腾讯从三大运营商拉过来的专线对等的,我再说的通俗一点,如果你家里宽带有 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 回复
  • zxhd86

    数据库和索引是不经过同步的,它们放在 temp 目录下。

    调用一堆内核 api 跟很多数据发生变化无关,我指的是打开 siyuan.log,看这一堆东西的上下文:

    I 2024/08/17 00:06:34 s3.go:94: uploaded object [repo/objects/c4/0294c4d4c1c85d1d3c85d9ad8527c8988d4121]
    I 2024/08/17 00:06:34 sync.go:1265: uploaded chunk [objects/c4/0294c4d4c1c85d1d3c85d9ad8527c8988d4121, 561/6604]
    I 2024/08/17 00:06:34 s3.go:94: uploaded object [repo/objects/cf/5e4f6bad5e4a80d2e2e596b5bb084eb1447915]
    I 2024/08/17 00:06:34 sync.go:1265: uploaded chunk [objects/cf/5e4f6bad5e4a80d2e2e596b5bb084eb1447915, 562/6604]
    I 2024/08/17 00:06:34 s3.go:94: uploaded object [repo/objects/89/24958a3954bd9c8bad705e0f6a03a8d33f6273]
    I 2024/08/17 00:06:34 sync.go:1265: uploaded chunk [objects/89/24958a3954bd9c8bad705e0f6a03a8d33f6273, 563/6604]
    I 2024/08/17 00:06:34 s3.go:94: uploaded object [repo/objects/d9/2c22093eaa028952d2a912f5af45c8a24d0328]
    I 2024/08/17 00:06:34 sync.go:1265: uploaded chunk [objects/d9/2c22093eaa028952d2a912f5af45c8a24d0328, 564/6604]
    I 2024/08/17 00:06:34 s3.go:94: uploaded object [repo/objects/60/3ddb05be9c7b26b7b962eb6bd4948c50a78915]
    I 2024/08/17 00:06:34 sync.go:1265: uploaded chunk [objects/60/3ddb05be9c7b26b7b962eb6bd4948c50a78915, 565/6604]

    它们就是实际上传下载的数据分块,如果数量小,时间短,那就说明并不是在这一步阻塞的。

  • 查看全部回帖

推荐标签 标签

  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 214 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 6 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 2 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    124 引用 • 74 回帖 • 1 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖 • 1 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 393 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 8 关注
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    132 引用 • 796 回帖
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 350 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖
  • SQLite

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

    5 引用 • 7 回帖 • 1 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    226 引用 • 476 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 108 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 545 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    169 引用 • 1527 回帖
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 76 回帖 • 2 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖 • 1 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 3 关注
  • Pipe

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

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

    132 引用 • 1115 回帖 • 118 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    21 引用 • 204 回帖
  • 禅道

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

    6 引用 • 15 回帖 • 34 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 18 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 34 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 2 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 413 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 638 关注