FastComments.com Blog

Sun Mar 29 2026
...

FastComments 準備好進軍太空!

! 本文包含技術術語

新聞

每個 FastComments 接入點 現在都可以在本地寫入,並異步將這些寫入複製到所有其他節點。這將提供比之前系統更高的耐用性,同時使一些地區的用戶的審核工具更快,儘管會有一些取捨。

「準備好進軍太空」有點樂觀,但這個想法是我們能夠將 FastComments 部署到不同的行星,最終系統將達到同步。然而,冥王星上的用戶將不得不等大約一天才能在即將發出的發票頁面上看到變更,因為目前每個區域只能有一個主節點聚合計費資訊。

一些歷史,為何改變

當 FastComments 最初推出時,我們有一個非常典型的架構。我們有一個代理層、一個應用層、一個資料庫、一些副本,後來在不同區域和雲服務提供商之間增加了副本以增強冗餘。

最終,我們將資料庫副本移動到用戶最多的所有區域,並且在那裡部署了應用,還創建了我們自己的 DNS 和代理系統(在後續的部落格文章中描述)來將請求路由到最近的應用節點。這樣可以加快讀取速度,但寫入速度變慢,因為現在不再需要等待一次 HTTP 往返回到後端,而是需要等待一次 HTTP 往返到近端節點,而該節點可能會進行多次寫入回主節點。這樣不好!

因此,為了解決這個問題,我們重新結構了應用的許多區域,以在函數參數中接受 readPreference,這樣調用者可以決定他們對讀取過時數據的接受程度,並且在此基礎上使得更多的寫入(例如在審核操作中寫入審核者統計信息)為火並忘。這雖然不是理想,但確實顯著加快了速度。

我們在 Mongo 全球運行中遇到的一個問題是網絡分裂。如果足夠多的節點被切斷,讀取就會停止,因為每個節點都會不確定是否可以提供讀取服務。這有一些解決方案,但邊緣案例變得相當麻煩。這不是一個理論問題—這種情況發生過很多次,導致凌晨三點的警報,我們厭倦了這個情況,甚至嘗試調整 Mongo 以適應最多相差一分鐘的副本集選舉不確定性。可悲的是,例如從聖保羅到法爾肯斯坦的網絡,在我們的一些托管提供商中,就是不太好。調整擁塞控制等雖然有所幫助,但並沒有解決問題。

假設您接受某些取捨,那麼聖杯解決方案就是能夠在該節點本地接受寫入(該節點擁有良好的硬體、RAID 等,不太可能崩潰)並告訴用戶他們的數據已被保存。您還可以在該接入點處保留第二個節點作為熱副本,以加強持久性。

所以我們的結果就是這樣。俄勒岡州、維吉尼亞州、法爾肯斯坦、聖保羅、新加坡,都是自己的副本集並接受寫入。歐盟的部署(雖然只有三個 PoP)具有相同的行為。

工作原理

這部分在之前的條目中有些涵蓋,但長話短說就是這是 CRDT-lite。我們創建了一個代理(用 Rust 實現,因為當然)在應用和 Mongo 之間,讓它成為多主模式。這個代理是點對點意識的,管理檢查點、複製、監控和初始同步。它是 Mongo 中複製系統的多主替代方案,包括某些 DDL 命令。

與其他工具的區別在於這不尾隨 oplog。尾隨 oplog 或使用變更流都無法實現,因為它們僅顯示寫入後對象的最終狀態,這使得處理衝突變得不可能。您需要捕捉每個 $set$inc 操作並複製該操作本身。

這是一個特定領域的解決方案。它不會對所有產品起作用。可以說這是域驅動設計 :)。它之所以適用於我們,是因為從一開始我們非常小心地僅 $set 我們在文件中更改的字段—例如,我們從不使用 Mongo 的 replaceOne。對於計數器也是如此。您永遠不會執行 SET VOTES = 5。相反,您應該寫 INCREMENT VOTES BY 5,這樣可以實現最終一致性。分佈式鎖通過完全避免它們來處理。每個集群中只有一個節點設有標誌來運行 crons。雖然這可能看起來有限,但我們可以購買擁有 TB 記憶體的伺服器,因此我們可以接受這種取捨,以降低風險和複雜性。

讀取自己的寫入

對於使用 API 的開發者,您應該能像以前一樣讀取自己的寫入(進行 API 調用以創建註解,然後列出註解並在該列表中查看新條目)。但要注意,這不能跨區域進行。如果您的後端僅在一個區域內運行,例如 us-west,那麼您應該能夠讀取自己的寫入,除非在您的寫入和讀取之間,該節點宕機 您的 DNS 快取更新為指向最接近的節點。只要不發生這種情況,讀取自己的寫入是可靠的。

測試和遷移

系統中約一半的代碼是測試工具、框架和測試。儘管如此,發布過程有點坎坷,停機時間比預期的要長(歐盟1小時,全球20分鐘),但我們很高興能夠通過這個里程碑,感謝您的耐心!

總結及對您的意義

FastComments 現在應該比以往任何時候都更快、更耐用,現在我們可以回去專注於功能開發 :)

乾杯!