老柯修机铺

通讯行老师傅的手机软件笔记——每款 App 装过、用过,才敢写下来

Syncthing 點對點同步原理:從哈希分塊到版本控制的完整路徑

Syncthing 是一款不經任何中心服務器的開源檔案同步工具,本文從技術拆解角度講解其哈希分塊、TLS 證書、掃描機制與版本控制四大核心設計,以及每個設計背後的取捨。

開源點對點檔案同步:為什麼 Syncthing 不需要雲端也能跑

先說清楚 Syncthing 是什麼——它是一款完全開源的檔案同步軟體,讓你的手機、電腦、NAS 之間直接互相同步照片、文檔、專案檔案,數據從來不經過任何第三方雲端。整個同步集群就是你的幾台設備,它們互相發現、互相驗證、互相傳輸。

作為一個長期關注開源同步領域的人,我一直對一個問題著迷:這種沒有中心服務器的架構,到底怎麼做到「你改了一個檔案,半分鐘內另一台設備就收到變化」?它靠什麼判斷哪些內容變了、哪些塊不用再傳?它怎麼確定對方是你信任的設備而不是入侵者?還有,當同步把我的舊檔案覆蓋掉時,它有沒有留後手?

這篇文章會把這些問題逐個拆開,從底層的哈希計算一路講到版本控制的四種策略,每個設計背後都有取捨——理解了取捨,你才知道它適不適合你的場景。

安裝

Syncthing 本體是跨平台的 Go 語言實現,Android 客戶端由社區分支維護(包名 com.nutomic.syncthingandroid)。安裝包約 48.67MB,最新版本 1.28.0。Android 端從 Syncthing下載 獲取 APK 後,允許「安裝未知來源應用」即可。首次啟動時應用會請求存儲權限——這一步不能跳過,否則同步目錄無法建立。

電腦端的體驗因平台而異。macOS 用戶最省事:官方提供標準 .dmg 應用包,拖進 Applications 就裝完了,自啟動在系統設置裡管理即可。Linux 用戶可以從包管理器安裝,也可以從發布包解壓;後者需要手動配置 launchd(macOS)或 systemd(Linux)服務文件才能做到開機自啟。Windows 用戶推薦官方提供的 GUI 集成包,它會自動處理後台進程與自啟動項。

安裝完成後的第一步不是馬上加同步目錄——先把設備 ID 記下來。每台設備首次啟動時會自動生成一張 TLS 證書,證書的 SHA-256 指紋就是這台設備在集群裡的唯一身份標識。兩台設備要互相同步,必須各自手動輸入對方的設備 ID 才能建立信任關係。這一步比賬號密碼制繁瑣,但換來的是:沒有任何服務商能冒充你的設備、沒有密碼洩露風險。

Syncthing 首次啟動顯示設備 ID 與當前連接狀態

哈希分塊:它怎麼知道哪部分變了?

同步的核心難題不是「傳輸」本身,而是「什麼需要傳輸」。如果每次同步都把整個檔案重新傳一遍,那跟直接上傳雲盤沒什麼區別。Syncthing 的解法是 SHA-256 分塊哈希。

每個檔案在首次掃描時會被切成固定大小的塊(默認 128KB),對每塊計算一個 SHA-256 哈希值。這些哈希值匯成一個索引,隨檔案元信息(路徑、大小、修改時間)一起在設備間傳遞。同步時,雙方先交換索引——只要某個塊的哈希值對不上,就知道這塊有變化,只傳這一塊就夠了。

這個機制帶來的好處很直觀:你在一份 50MB 的 PDF 上只改了一句話,同步時只傳包含那句話的那一個 128KB 塊,剩下 49.875MB 全部跳過。對於經常修改大檔案的場景(視頻剪輯工程、虛擬機鏡像),增量帶寬節省可以達到 90% 以上。

但哈希計算本身是有成本的。Syncthing文檔 把 CPU 消耗的四個來源排了序,其中 SHA-256 哈希排在第一——特別是首次同步階段,所有檔案都要逐塊計算。程序默認會降低自身進程優先級(setLowPriority),避免佔用前台應用的算力。如果你的設備是低功耗裝置(NAS、樹莓派、老款安卓手機),可以通過設置環境變量 GOMAXPROCS 來限制最大使用的 CPU 核心數,把後半個核心留給系統其他服務。

掃描機制:它怎麼及時發現變化?

知道了「怎麼比對」,下一個問題是「什麼時候比對」。Syncthing 的掃描機制其實是兩層設計:

第一層是 watcher,即操作系統提供的檔案系統事件監聽。它默認開啟,當你在同步目錄裡新增、修改、刪除檔案時,操作系統會立刻推送一個事件,Syncthing 收到後立即重新計算那個檔案的哈希並更新索引。這就是為什麼多數情況下你改完檔案,幾秒鐘後另一台設備就同步到了——根本沒有等到定時掃描。

但 watcher 並不是絕對可靠的。官方文檔承認某些場景下 watcher 會漏報(例如網路驅動的網路文件系統、某些 Android 製造商自定義的存儲堆疊),所以有第二層 定時全掃描 作為兜底。默認每小時一次完整掃描,而且掃描時刻會在設定間隔的 3/4 到 5/4 之間隨機偏移——這個細節很重要,因為集群裡多台設備如果同時掃描同一個大目錄,會產生短暫的 CPU 峰值。隨機偏移把這些峰值打散了。

掃描間隔是可以按文件夾單獨調整的——大而少變的目錄(比如一個電影資料庫)可以拉長到 6 小時甚至 12 小時,省下大量無用的掃描開銷;而頻繁修改的工作目錄保持默認就好。

TLS 證書與設備 ID:信任鏈是怎麼建立的?

前面安裝小節提到了設備 ID,但這裡值得再深入一層。每台設備首次啟動時會自動生成一張自簽名的 TLS 證書,證書的 SHA-256 指紋就是設備 ID——一串看起來像亂碼的十六進制字串。

兩台設備要建立連接,流程是這樣的:A 掃描到 B 的設備 ID,手動輸入;B 同樣輸入 A 的設備 ID。此後 A 發起連接時,B 會出示自己的證書,A 驗證指紋是否匹配之前手動輸入的那串字串。匹配得上才允許建立 TLS 通道。

這個機制的本質是 預共享的指紋驗證——與 SSH 的主機密鑰信任邏輯完全一致。沒有人能靠猜測或偽造通過驗證,因為指紋空間是 256 位;也沒有人能攔截你的同步流量,因為所有傳輸內容都在 TLS 通道裡加密。代價就是初始設置比賬號制繁瑣——你得真的走到另一台設備旁邊把那串字符抄下來。官方 FAQ 直接承認這是「安全優先於便利」的取捨。

版本控制:被覆蓋的舊檔案去了哪?

同步不是備份。這是 Syncthing 官方文檔反覆強調的一個觀念——同步會把多台設備的狀態趨同,如果你在一台設備上誤刪了一個檔案,同步過去後其他設備上的副本也會消失。版本控制就是為這個場景留的一手。

開啟版本控制後,當遠端設備的改動覆蓋或刪除了本地檔案時,舊版本不會直接消失,而是先被歸檔到同步目錄裡的 .stversions 文件夾。這裡有四種策略可選:

回收站式(Trash Can) 最省心——舊版移入 .stversions,按天數定期清空,適合大多數普通用戶。簡單式(Simple) 在此基礎上多加了「每檔案最多保留 N 個版本」的限制,想控制磁碟佔用的場景用它。交錯式(Staggered) 是長期留檔的最佳選擇——它按時間梯度自動精簡:30 秒內的全部保留、1 小時內的減半、1 天內的再減半、1 週內的只留幾個,最老的檔案設一個最大年齡就自動清除。NAS 用戶首選這個策略。外部式(External) 則把舊版的處理權交給一條外部命令——可以送系統回收站、可以上傳到異地備份,完全自定義。

有一個關鍵限制必須講清楚:版本控制只處理從其他設備同步過來的改動。如果你在自己的設備上手動改壞了一個檔案,Syncthing 不會也無法幫你歸檔舊版——因為它不知道你是不是故意改的。這部分保護要靠真正的備份工具來解決。

取捨與判斷

把上面幾個設計串起來看,Syncthing 的整體哲學就清晰了:它是一個 協作型同步工具,不是雲盤、不是備份、不是即時通訊。每個設計都在「安全與隱私」這一側加了砝碼,代價是初始設置繁瑣、低功耗設備上有 CPU 開銷、版本控制的保護範圍有限。

我用一個生活化的類比來幫你判斷:Syncthing 就像一個只有幾個熟人的私人群組——每個要進群的人都得互相認證身份(設備 ID 配對),群裡說的話只有成員能看到(TLS 加密),而且沒有人能撤回別人發的消息(本地修改不觸發版本歸檔)。如果你需要的是「把文件丟上雲盤、隨時隨地從任何設備取回」,那它不是你要的;但如果你在意數據隱私、不想把私人檔案交給任何公司存儲、又有多台設備需要保持一致的工作環境,Syncthing 是目前開源領域最成熟的解法之一。

最後補一個細節:當然也有閉源方案能做到點對點同步——比如 Resilio Sync。它曾經走過開源路線(BitTorrent Sync 時代),後來閉源了,現在的協議未公開、安全屬性無法獨立審計。Syncthing 選擇了另一條路:協議規範公開、代碼全部可審、沒有賬號體系、沒有訂閱費用。這兩條路沒有對錯,純粹是你把砝碼加在哪一側的問題。

本文为个人基于网络公开资料整理编写,非官方内容,仅供学习交流参考;软件版权归原作者所有,请支持正版;使用过程中遇到问题请查阅官方渠道,本文不承担任何责任。

同类文章

ChromeCast 隱藏功能挖一輪:你以為它只能投屏?

大眾印象裡 ChromeCast 就是個「手機往電視扔片子」的工具,但我把它翻了個底朝天,挖出幾個大多數人不知道的隱藏設定與冷門技巧。從原畫質直通、鎖屏不斷線到安卓 13 的權限陷阱,這些細節決定你投屏體驗是順還是卡。