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

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

太长不看:

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

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

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

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

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

  • 思源笔记

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

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

    28441 引用 • 119746 回帖

相关帖子

优质回帖
  • tianzhongs 1 赞同

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

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

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

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

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

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

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

    image.png

欢迎来到这里!

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

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

    这倒是,这样就绝对不用担心文件被外部占用了trollface

  • 其他回帖
  • zxhd86

    对象储存高并发支持得不好吗?

    可悲的是,确实不高,我自己手动修改了并发数后运行的效果确实如果。可能 minio 的性能有限,可能官方同步在控制台对于并发数做了限制,但是事实就是,大量小文件的并发上传和下载速度并不好。

    可能花尽心思搞一堆东西,也就优化个一两秒

    这倒不能这么说,只使用 s3 的 obsidian livesync 算是为我们揭示冷备份方案的上限了,他确实没有在云端运行一个实例的。就算算上思源跟 livesync 建立同步上的差异,对于 20mb、650 个文件的同步,那也能从 90s 砍到 4(建立快照) + 3s,这是极大的提升了。

    就做一个最简单的同步,单纯从打开窗口或者后端 api 请求判断哪个 sy 文件发送了改变,上传了哪些文件,删除了哪些文件,禁止 fs,真正的按需同步,也比现在快

    不太行,因为有外部修改的因素,不考虑这个就确实可以。

    obsidian 使用了 node 的 fs.watch 来递归监听文件夹变化,它也不是靠监听窗口和自身的修改动作实现文件修改事件的监听的。livesync 归根结底也是调用了 obsidian 的这个接口。可惜,golang 没有这么方便的东西,有归有,但是 windows、linux、mac 各有各的接口,头都大了。目前最有希望的还是使用轮询机制动态监听,而不是在同步时才扫描文档、建立快照。

    但现在恐怕连修改了 3 个字就只同步这个文档的操作都没做到

    这个据我所知应该是实现了?不过每次同步最少是要上传、下载一份索引,这个索引体积依照 data 而定,我的 data 大概需要 134kb 的索引,emmm……

    1 回复
  • 我想向你描述的很清楚了,包括你现在又说伺服,我一开头表达的很清楚

    同步目前最简单粗暴的增本增效的方法就是,直接在服务器上给每个订阅用户运行自己的思源内核实例,在使用官方同步的情况下,客户端后端直接与云端内核通信,离线状态下客户端自己记录距离上一次同步的离线时间戳,每当与云端内核连接,就开始对比数据新鲜度,而冲突解调在云端内核进行

    代表我不是不知道伺服可以最快解决,但是你不能作为一个官方订阅,让用户自己伺服吧,所以我直接说了云内核,增本增效。

    但是说实话,就做一个最简单的同步,单纯从打开窗口或者后端 api 请求判断哪个 sy 文件发送了改变,上传了哪些文件,删除了哪些文件,禁止 fs,真正的按需同步,也比现在快,大家当然想要如果修改了 3 个字,就只做同步 3 个字的操作,但现在恐怕连修改了 3 个字就只同步这个文档的操作都没做到

    这个是想表达,储存器性能根本不是原因,是自己没做足够复杂的中间件处理,最为全世界广泛应用的技术,对象存储已经是最好的云端存储方案了,就好像是,能不能让博尔特再快 5s,这样我看他跑步时间就更短了,有没有可能是自己阈值太高?

    然后就是,我也没有把 live 看成是什么标杆,它也是早轮子而已

    说白了,你觉得很简单的东西,像 live 做的监听对象,思源加了没有?最后我说这么多,我觉得最核心的还是这个

    从去年讨论到现在,关于同步已经讨论了无数多个先进方案了。我的评价是,别自嗨,主要看 D 怎么说

    1 回复
  • 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
  • 查看全部回帖

推荐标签 标签

  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 667 关注
  • OpenShift

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

    14 引用 • 20 回帖 • 687 关注
  • Shell

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

    126 引用 • 83 回帖 • 1 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    421 引用 • 3610 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    285 引用 • 248 回帖
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    85 引用 • 324 回帖
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    89 引用 • 1251 回帖 • 378 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    182 引用 • 400 回帖
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    293 引用 • 4496 回帖 • 687 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    25 引用 • 373 回帖 • 6 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 10 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 3 关注
  • RabbitMQ

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

    49 引用 • 60 回帖 • 342 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 236 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    695 引用 • 538 回帖 • 1 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 27 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    736 引用 • 1307 回帖 • 2 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 10 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 90 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    27 引用 • 7 回帖 • 94 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    91 引用 • 59 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖 • 1 关注
  • OnlyOffice
    4 引用 • 40 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • FlowUs

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

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

    1 引用 • 1 关注
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 56 关注