手机里存了大半年的照片、录音、微信里存下来的文件,我一直想让它自动落到电脑硬盘上,而不是每次插线复制一遍。试过网盘的同步盘,会员一到期就开始往下压速度;试过各种传输工具,两边都得有人盯着点确认,传完还得手动归类。后来把 Syncthing 在两台机器上挂了几天,才算把这件事变成一个不用管的背景动作。
它同步的是文件夹,不是网盘
这一点先说清楚,不然容易失望。Syncthing 没有云端,也没有「上传」这个概念:你指定 A 机器的一个目录、B 机器的一个目录,两边确认共享,之后任何一边的增删改都会推到另一边。数据不在任何第三方服务器上停留,两台机器直连,走 TLS。
所以它替代的是网盘客户端里那个「同步文件夹」,而不是网盘的在线存储。好处是不占云空间、不怕服务商改规则、局域网内速度只取决于你的路由器和硬盘;代价是没有分享链接、没有在线预览、删了就真删了。
我这两天的实测数据
我拿 v2.1.7 的 Windows 版做了组测试:同一台机器上开两个实例,一个发一个收,中间走 127.0.0.1 回环,把网络因素排除掉,只看软件本身的开销。硬件是 Ryzen 5 3550H、SSD、8 线程。
- 压缩包 14.28MB,解压出来就一个 33.19MB 的 syncthing.exe,没有安装程序、没有运行时依赖
- 从启动到网页接口返回 200:229ms 和 227ms
- 1000 个约 2KB 的小文件:6.69 秒全部到位,这个时间含扫描目录和写索引
- 500 个同类小文件:3.66 秒
- 单个 200MB 文件:5.12 秒,折合 39.1MB/s
- 传完之后发送端工作集 86.2MB、私有 110.4MB、51 个线程、504 个句柄;接收端 49.5MB、71.4MB、30 个线程
- 整个过程 CPU 累计:发送端 8.61 秒,接收端 13.86 秒
小文件那一项比大文件更值得看。1000 个 2KB 的文件加起来才 2MB 出头,却花了 6.69 秒;200MB 的单文件反而只用 5.12 秒。瓶颈不在带宽,而在于每个文件都要单独建索引、算块哈希、落一条记录。所以别把 node_modules、缓存目录这种碎文件堆往里塞,同步会慢到你以为它挂了。
39.1MB/s 这个数在回环上不算漂亮。千兆局域网的理论上限是 110MB/s 左右,Syncthing 一般跑不满,因为每个块都要做一次 SHA-256,接收端还要再验一遍。上面接收端 CPU 比发送端多出 5 秒,基本都花在二次校验上。想在局域网里跑快,硬件上更该关注 CPU 单核性能和 SSD 随机读写,而不是换个更贵的交换机。
索引换成了 SQLite,旧教程别照抄
v2 之前索引是 LevelDB,现在打开数据目录会看到一个 index-v2/ 文件夹,里面是 main.db 和 folder.0001-xxxx.db 这类 SQLite 文件,还配着 -wal 和 -shm。我这边 1002 个文件之后,整个索引目录 2.4MB,其中 2.2MB 还压在 WAL 里没合并。
这带来两个实际影响。一是备份思路要变:光拷 config.xml 不够,索引和配置是分开的,v2 起可以用 -C 指定配置目录、-D 指定数据目录。二是拷数据目录必须停进程,WAL 还在写的时候直接复制,很容易拿到一个半截的库,起来之后要么重建索引,要么直接报错。
更麻烦的是命令行全变了。以前满地的 syncthing --home=... 现在会直接报 unknown flag -o,因为参数解析换了新的。现在长这样:
syncthing serve -H D:\st-data --no-browser --no-restart
serve 是个子命令,-H 表示配置和数据放一起;想分开就用 -C 和 -D。网上大部分教程还停在 v1 的写法,照抄会卡在第一步。
手机上怎么接进来
安卓装 Syncthing-Fork,官方那个客户端早就停更了;iPhone 没有官方客户端,得找第三方。两边都起来之后:
- 电脑上打开 http://127.0.0.1:8384,右下角「操作 → 显示设备 ID」,会出来一串带连字符的字母。
- 手机端添加远程设备,扫电脑这个 ID 的二维码。
- 电脑端会弹「新设备想连接」,接受。
- 电脑上选好要共享的文件夹 → 编辑 → 共享 → 勾上手机;手机端接受这个文件夹,指定落到哪个目录。
端口记三个:8384 是网页界面,22000 是设备之间的传输,21027 是局域网里互相发现用的。路由器上只放 22000 就够,8384 千万别往公网开——那个界面默认没有密码。
三个真实的坑
一、把进程挂进脚本、输出接了管道却没人读,会假死。 我第一版是写了个脚本起进程,顺手把 stdout 接成管道方便抓日志,结果同步跑到 321 个文件就不动了,两边都不报错,等了十几分钟一点没推进,看着像协议卡住。把输出改成写日志文件之后,同样 1000 个文件 6.69 秒跑完。管道缓冲区满了以后进程写日志就阻塞在那儿,看起来是同步卡死,其实是被自己的日志噎住了。用计划任务或者自己写的守护脚本挂 Syncthing 的人,这个坑很容易踩。
二、两边同时改同一个文件,文件名会变长。 我在两端同时改 conflict.txt,几秒后两边目录里都多出一个 conflict.sync-conflict-20261101-032643-VJRXEUX.txt,时间戳加设备前缀。原文件名留下的是后写入的那份,另一份改名留着。这个设计不丢数据,但目录里会慢慢积一堆长名字文件,手机相册目录里尤其明显,得定期清。
三、状态接口别按秒轮询。 /rest/db/completion 空闲时单次 9.1ms、p90 13.8ms,同步过程中会涨到 90ms 左右,因为它每次都去数一遍还差多少项多少字节。写监控脚本的话 5 秒一次足够,按秒轮询只会跟同步抢 SQLite。
它不适合干什么
一次性传个文件给同事,用 LocalSend 更省事,Syncthing 是长期挂着的文件夹,不是传输工具。想当网盘用也不行,没有分享链接、没有版本历史、没有回收站。另外手机端最大的敌人是省电策略:安卓厂商会直接把后台的 Syncthing 干掉,必须手动加进电池白名单、关掉优化,不然它永远是「正在等待」。
我现在是把手机相册、录音、微信存下来的文档分三个文件夹共享给主机,主机侧再定时往移动硬盘做一次冷备。跑了几天没出过冲突,唯一要管的是偶尔清一下同步冲突文件。
你们那边是怎么把手机里的东西自动落到 NAS 或主机的?挂 Syncthing,还是直接用相册 App 自带的备份?