當前位置: 妍妍網 > 碼農

從MongoDB到PostgreSQL:數據零遺失、成本砍半

2024-05-13碼農

Infisical 是一家開源的金鑰管理平台,為團隊及基礎設施提供同步金鑰的服務並防止金鑰泄露。隨著業務不斷發展、數據不斷增加,原有資料庫已無法滿足當前需求,Infisical 決定從 MongoDB 遷移到 PostgreSQL 。本文將分享這一從非關系型資料庫遷移至關系型資料庫的決策判斷及背後的遷移故事。

Infisical 在過去一年裏迅速擴張,目前平台每天處理超過 5000 萬個金鑰,向需要數據的團隊、CI/CD 管道以及伺服器/應用程式,發送應用程式配置和機密數據。

隨著使用量不斷增加,我們必須持續升級技術棧。最近,Infisical 進行了從MongoDB到PostgreSQL的資料庫全面遷移。此次遷移 涉及到對方案的審慎評估、采納新技術、建立新的資料庫模式(schema)、重構邏輯、重寫查詢語句 ,將數百萬(如果不是數十億)的資料庫記錄遷移到 PostgreSQL。這過程十分復雜,但也是改善平台的必要一步。

本文將介紹我們 從 MongoDB 遷移到 PostgreSQL 決策 背後的故事以及遷移過程。希望這篇文章令人感興趣,並為其他考慮進行類似資料庫遷移的人提供幫助。

從何開始

最初構建 Infisical 時,我們選擇了團隊最熟悉的技術棧進行構建。作為這個方案中的一部份,我們選擇了 MongoDB + Mongoose ORM, 因為這種組合的開銷最小,並提供了快速交付高品質的功能。

正如東尼·霍爾爵士所說,「 過早最佳化是萬惡之源 」,也確實沒有進一步最佳化的必要,我們當時還專註於構建 Infisical Cloud(托管 SaSS 產品)。同時由於這一產品側重點,我們並沒有預計到有很多使用者自行托管產品,所以也沒有對這一用例設計相關方案。

為什麽放棄 MongoDB?

雖然 MongoDB 在早期為 Infisical 提供了良好服務,但當我們產品場景發展到超出托管服務範圍時,它開始顯示出不足。隨時間推移,我們發現許多組織,尤其是在合規性和安全性的交叉領域營運的組織,相較使用Infisical Cloud,更喜歡自托管 Infisical;同時使用者也有些需要滿足的本地需求。

隨著對自托管 Infisical 的需求不斷增長,我們發現已經開發了相當多功能來減少自托管 Infisical 所需的學習曲線,而在這一趨勢的影響下,我們最終放棄了 MongoDB,轉而使用 PostgreSQL。

在實踐中,我們和我們的客戶經常在功能和可用性方面受到 MongoDB 的限制,例如缺乏對 事務、清理的支持、雲廠商托管產品的版本控制不一致,更不用說無模式(schema-less)資料庫設計結構等相關問題。

下面詳細闡述其中的一些挑戰:

  • 配置資料庫事務困難: 使用MongoDB設定事務並不容易,因為它需要在集群模式下執行 MongoDB,並產生各種配置開銷。由於需要MongoDB 的生產設定,客戶執行簡單的 Infisical POC 變得極其困難。對於處理高度敏感數據且必須保證數據完整性的產品來說,這是難以接受的。

  • 缺少關系型功能: 使用 MongoDB,意味著失去了關系型世界中的許多優秀功能,例如 CASCADE ,每當刪除目標資源時,就可以刪除其他表中參照的所有資源;這造成了相當大的損失,因為我們的數據很大部份是關系型。所以,我們在舊程式碼庫中使用了大量的刪除函式,但這些函式從未完全完成工作,並在 MongoDB 資料庫中留下了懸置資源。

  • 缺乏跨雲提供商的支持: 在 MongoDB 將授權證更改為 SSPL 後,許多雲提供商選擇提供舊版本的 MongoDB。因此我們發現,除了使用最新穩定版本MongoDB 的客戶外,很難確保執行在其他版本上 Infisical 的功能可用性。

  • MongoDB 實操經驗不足: 由於更多人熟悉部署基於 SQL 的資料庫,他們常常難以擴充套件和正確配置 MongoDB;這導致我們需要為客戶提供的支持量大幅增加,特別是因為他們不熟悉 MongoDB。

  • 除了以上及其他原因之外,我們還意識到,將完整的資料庫遷移到更通用的東西是讓世界各地的團隊和組織更容易使用 Infisical 所需的最終功能。

    選擇 PostgreSQL 的原因?

    在尋找新資料庫時,我們先列出最看重的幾個方面:易於管理(即包括配置、部署和擴充套件)、內建事務支持以及關系型功能。我們還考慮了是否應該構建自己的整合儲存或尋求外部儲存解決方案。

    以下是備選方案:

  • 整合儲存: 可以將SQLite等資料庫系統直接打包到 Infisical 中,並采用水平復制策略,透過避免額外的網路跳轉來減少延遲。在此模型中,擴充套件系統意味著部署多個 Infisical 例項,並讓它們透過Raft 等 共識演算法相互通訊。雖然這似乎是一個出色的解決方案,因為客戶不需要連線任何依賴項就能執行 Infisical,但執行此願景的工具生態系還不成熟,而且所需的工程工作有些強人所難。

  • 外部儲存: 可以簡單地將 MongoDB 替換為其他資料庫(例如 PostgreSQL 或 MySQL),並使用其內建的擴充套件功能。盡管該解決方案並沒有完全消除 Infisical 使用時需要外部依賴項的問題,但我們認為這項方案由於不使用 MongoDB 而帶來了顯著優點。討論到支持一個或多個資料庫時,我們認為支持多個資料庫意味著會失去各個解決方案的獨特優勢,同時增加的工程開銷。

  • 經過慎重考慮,我們選擇了PostgreSQL。除了擁有充滿活力的社群、廣泛的文件以及眾多可用的解決方案和擴充套件之外,我們最欣賞它的開源特性和絕大多數雲提供商都支持 PostgreSQL 托管服務。

    最重要的是,這意味著 Infisical 的使用者可以更輕松地在任何雲提供商上自行托管我們的平台,並將其與相應的托管 PostgreSQL 服務配對。此外,鑒於 PostgreSQL 已得到廣泛采用,我們相信使用者在使用 Infisical 時操作會更加便捷。

    如何處理 ORM?

    選擇 PostgreSQL 後,我們需要弄清楚應用程式如何與資料庫互動。我們第一反應是找到一些與使用 Mongoose ORM 的 MongoDB 體驗類似的工具。因此,我們開始根據成熟度、視覺化和遷移支持以及適當的抽象級別來評估候選工具;我們主要考慮了 Drizzle ORM、 Prisma ORM、 TypeORM和 Knex.js (一種查詢構建器)。

    最後,我們決定使用 Knex.js而非 ORM ,以便更好地控制資料庫。無可否認的是,原始 SQL 是最通用的且抽象最少,但我們認為這種方法太容易出錯,而且坦白說,在沒有適當的TypeScript 支持的情況下,維護起來很麻煩。

    此外,除了接近裸露的 SQL 之外,Knex.js 還內建用於播種和遷移工具包,擁有成熟的生態系,其中包含出色的文件和幾乎任何可能查詢的答案。再加上一些客製的 Zod 整合工作,我們盡力使其對 TypeScript 的支持達到了令人滿意的水平。

    在決定了資料庫和 ORM 後,我們啟動了一個流程,最終導致整個應用程式重寫數十個數據結構和數百個查詢。

    我們如何計劃遷移?

    程式碼重寫即將結束之時,我們開始考慮如何進行遷移操作,將 MongoDB 數據對映到 PostgreSQL,同時將對 Infisical 雲平台的幹擾降至最低。

    鑒於 Infisical 在客戶基礎設施中的關鍵作用,我們立即排除了絕對停機方案的可能性。我們不得不妥協的是,在短暫的遷移視窗期間禁止寫入操作(即客戶將無法建立或更新應用程式配置),以換取更高的數據完整性保證。這種權衡似乎可以接受,因為客戶主要從 Infisical 獲取機密資訊,並且他們每秒更新其應用程式配置的可能性較少。

    接下來,關於實際的遷移操作,我們需要從 MongoDB 轉儲數據、仔細轉換,然後將其插入回 PostgreSQL。在稽核遷移順序時,我們克服了一些挑戰,例如確保 NoSQL 中的各種樹狀結構正確轉換為其關系對應結構;這對於具有遞迴考慮的資料夾等數據結構尤其敏感。

    我們還發現需要一種持久的方式來儲存 MongoDB 中的識別元並將其對映到 PostgreSQL 中的識別元;考慮到處理的數據量之龐大,在記憶體中這樣操作是行不通的。最後,我們決定使用 LevelDB 鍵值儲存來協助識別元儲存和尋找操作,將數據逐表移動到 PostgreSQL 中。

    遷移

    最後,我們準備好進行遷移。此時,沒有直接參與程式碼庫重寫的人員用了一個季度的時間來改進 Infisical 的其他方面,包括進行前端更改、執行維護修補程式、擴充套件客戶端功能以及編寫更好的文件。此時,所有人重新聚集起來,為遷移這一過程做準備——把應用程式程式碼庫替換為新程式碼庫,並將數據從 MongoDB 傳輸到 PostgreSQL。

    作為準備工作的一部份,我們起草了一份詳細的遷移清單以及預期時間表。

    計劃大體如下:

  • 執行遷移的幾周前,透過電子信件和套用內橫幅提前通知使用者資料庫即將進行升級。我們將對平台上的每個功能流程進行徹底測試,並對遷移進行試執行。

  • 遷移過程預計六小時,期間平台僅允許讀取操作。在此視窗期,我們將執行遷移指令碼,將數據從 MongoDB 移動到 PostgreSQL,檢查數據是否遺失,如果成功則將 DNS 切換到新例項。我們還有備用計劃,以防意外。

  • 遷移後,我們將解決殘留問題,並推出使用 In fisical 和 PostgreSQL 的新文件。

  • 準備好計劃,我們就著手執行了。

    遷移效果

    幸運的是,遷移執行順利,數據零遺失,僅有一些非必要功能出現故障;我們在隨後的36 小時內解決了這些問題,將對客戶的影響降到最低。

    遷移後,我們觀察到了許多好處:

  • 平台效能顯著提升 ,主要歸功於連線查詢最佳化。使用 MongoDB 時,平台常常透過低效的聚合查詢和多次網路跳轉來實作所需功能。例如,由於我們核心數據的關系特性,經常需要執行很多 $lookup 操作來模擬 SQL 中的連線;此類操作效率低下,同時通常需要相應地擴充套件資料庫和應用程式例項。遷移到 PostgreSQL 後,我們避免了這些低效操作,也降低了50%的資料庫支出。

  • 目前平台采用了 更好的數據驗證方式 ,植根於資料庫層而不是套用層。MongoDB 被設計為無模式,因此它依賴 Mongoose 的框架來定義數據型別、必需欄位和驗證規則。有了 PostgreSQL,我們就不會再面臨以往 Mongoose 許可權之外存取或修改資料庫時會出現的數據不一致問題。

  • 最後也是最重要的是,我們相信 Infisical 現在 更易於自行托管 ,客戶無需額外的配置開銷就能夠進行 POC,例如處理 Mon goDB 中的副本集以啟用事務功能。

  • 總體而言,考慮到當前的目標、任務範圍及執行效果,我們認為此次遷移非常成功。我們打算在今後獲得更多數據後公布更具體的結果。

    結論

    從 MongoDB 遷移到 PostgreSQL 從開始就不是一個容易的決定。總而言之,我們花了 3 到 4 個月的時間來執行該計劃,並圍繞為什麽這樣做、如何做等問題進行仔細規劃和討論,然後小心翼翼地執行這一切。

    對於閱讀本文的任何人, 我強烈建議在嘗試這樣一項大型工作之前,深入思考用例和實施方案。 總之,我非常高興一切都按計劃進行,我們能夠提供如此巨大的更新,這將為 Infisical 使用者帶來巨大的變化。

    非常感謝 Akhil Mohan 對遷移工作的大力支持,以及Infisical 公司其他所有人對遷移過程的協助。


    作者丨Tony Dang 編譯丨onehunnit

    來源丨infisical.com/blog/postgresql-migration-technical

    *本文為dbaplus社群編譯整理,如需轉載請取得授權並標明出處! 歡迎廣大技術人員投稿,投稿信箱:[email protected]

    活動推薦

    2024 XCOPS智慧運維管理人年會·廣州站將於5月24日舉辦 ,深究大模型、AI Agent等新興技術如何落地於運維領域,賦能企業智慧運維水平提升,構建全面運維自治能力!