跳到主要內容
OpenAI

2026年1月22日

工程

將 PostgreSQL 擴展至支援 8 億阿 ChatGPT 用戶

由技術人員 Bohan Zhang 撰寫

正在載入...

多年來,PostgreSQL 一直是最重要的幕後資料系統之一,為 ChatGPT 和 OpenAI 的 API 等核心產品提供支持。隨著我們的用戶群迅速增長,對我們資料庫的需求亦呈現指數級上升。過去一年,我們的 PostgreSQL 負載增長超過 10 倍,並且仍在迅速上升。

我們努力推進生產基礎設施以保持其增長,這揭示了一個新見解:PostgreSQL 的可擴展性能可靠地支援更大規模的寫入量龐大工作負載,程度比許多人以往認為可能的要大得多。該系統(最初由加州大學柏克萊分校的一支科學家團隊建立)讓我們能以單一主要 Azure PostgreSQL Flexible Server Instance(在新視窗中開啟) 及近 50 個分佈於全球多個地區的讀取複本,支援龐大的全球流量。這是關於我們如何在 OpenAI 擴展 PostgreSQL 規模的故事:透過嚴謹的最佳化和穩健的工程實踐,支援 8 億名用戶每秒數百萬次查詢;我們亦會分享沿路學到的關鍵心得。

我們最初設計中的裂縫

ChatGPT 推出後,流量以前所未有的速度增長。為了支援 ChatGPT,我們迅速在應用程式和 PostgreSQL 資料庫層面實施廣泛的最佳化,並透過增加實例規模進行垂直擴展,同時透過新增更多讀取副本進行水平擴展。此架構長期以來一直為我們提供良好服務。隨著持續改進,此架構繼續為未來增長提供充足的空間。

單一主機架構能滿足 OpenAI 規模的需求,這聽起來可能令人驚訝,然而,要在實際操作中實現這一點並不簡單。我們見過多次由 Postgres 過載引致的 SEV,而這些事件往往遵循相同模式:上游問題導致資料庫負載突然激增,例如快取層故障引致大範圍快取未命中、昂貴的多路連接激增令 CPU 飽和,或推出新功能引發的寫入風暴。隨著資源使用率上升,查詢延遲增加,請求開始逾時。重試則會進一步增加負載,觸發惡性循環,可能導致整個 ChatGPT 和 API 服務的效能下降。

縮放負載圖

儘管 PostgreSQL 在我們讀取量龐大的工作負載中具備良好的擴展性,但在高寫入流量時段,我們仍然面臨挑戰。這主要是由於 PostgreSQL 的多版本並行控制 (MVCC) 實現,使其在寫入量龐大的工作負載下效率較低。例如,當查詢更新一個元組,甚至更新單一欄位時,整行都會被複製以創建新版本。在寫入量龐大的負載下,這會導致顯著的寫入放大。此外,這也會增加讀取放大,因為查詢必須掃描多個元組版本(死元組)以擷取最新版本。MVCC 帶來額外挑戰,例如表格和索引膨脹、增加索引維護開支,以及複雜的自動真空調整。(你可以在我與卡內基梅隆大學 (Carnegie Mellon University) Andy Pavlo 教授合寫的一篇部落格中,找到對這些問題的深入分析,標題為 The Part of PostgreSQL We Hate the Most(在新視窗中開啟),該部落格在 PostgreSQL 的 Wikipedia 頁面中被引用(在新視窗中開啟)。)

將 PostgreSQL 擴展至每秒數百萬次查詢

為了緩解這些限制並降低寫入壓力,我們已經遷移,並將繼續遷移可分片的(即可進行水平分割的工作負載)寫入量龐大工作負載至分片系統(例如 Azure Cosmos DB),並最佳化應用程式邏輯,盡量減少不必要的寫入。我們亦不再允許在目前的 PostgreSQL 部署中增加新的表格。新的工作負載預設使用分片系統。

即使我們的基礎設施已經演變,PostgreSQL 仍然保持不分片,並由單一主要實例處理所有寫入。主要理據是,將現有應用程式工作負載進行分片非常複雜且耗時,需要更改數百個應用程式端點,並且可能需要數個月甚至數年。由於我們的工作負載主要為讀取量龐大,並且已實施大量最佳化,現有架構仍然提供充足空量,以支援持續的流量增長。雖然我們不排除將來對 PostgreSQL 進行分片的可能性,但由於我們目前及未來增長有充足空間,因此這並非近期的優先事項。

在以下各章節中,我們將深入探討所面對的挑戰,以及為應對這些挑戰並防止未來中斷而實施的廣泛最佳化措施,將 PostgreSQL 推到極限,並將其擴展至每秒數百萬次查詢 (QPS)。

減少主機負載

挑戰:只有一個寫入器的情況下,單一主機架構無法擴展寫入。龐大寫入量激增可能會迅速令主機超載,並影響 ChatGPT 及我們的 API 等服務。

解決方案:我們盡可能將主機的負載降到最低,包括讀取和寫入,以確保有足夠容量應付寫入激增。讀取流量會在可行時卸載至副本。然而,某些讀取查詢是寫入交易的一部分,因此必須保留在主機上。就此而言,我們專注於確保其效率,並避免緩慢的查詢。對於寫入流量,我們已將可分片且寫入量龐大的工作負載遷移到分片系統,例如 Azure CosmosDB。較難分片但仍會產生高寫入量的工作負載需要更長時間遷移,而該過程仍在進行中。我們亦積極最佳化應用程式以減少寫入負載。例如,我們修正了導致重複寫入的應用程式錯誤,並在適當情況下引入延遲寫入,以撫平流量激增。此外,在回填表格欄位時,我們會實施嚴格的速率限制,以防止過度的寫入壓力。

查詢最佳化

挑戰:我們在 PostgreSQL 中識別出幾個成本高昂的查詢。過去,這些查詢的突然流量激增會消耗大量 CPU 資源,導致 ChatGPT 和 API 請求速度變慢。

解決方案:一些高成本的查詢,例如將多個表格連接在一起的查詢,可能會顯著降低效能,甚至使服務全面停擺。我們需要不斷對 PostgreSQL 查詢進行最佳化,以確保其高效運行,並避免常見的線上交易處理 (OLTP) 反模式。例如,我們曾識別出一個成本極高的查詢,其連接了 12 個表格,該查詢的激增曾導致過往發生高嚴重性 SEV。我們應盡量避免使用複雜的多表格連接。如果必須連接,我們學會考慮將查詢分解,並改為把複雜的連接邏輯移動到應用程式層處理。許多這些有問題的查詢是由關聯映射框架 (ORM) 產生,因此必須仔細檢查其生成的 SQL,並確保其行為符合預期。在 PostgreSQL 中,長時間運行的閒置查詢亦十分常見。配置 idle_in_transaction_session_timeout 等逾時設定至關重要,以防止它們阻擋自動真空。

單點故障緩解措施

挑戰:如果讀取副本發生故障,流量仍然可以被引導到其他副本。然而,依賴單一寫入器意味著存在單點故障,如果它出現問題,整個服務都會受到影響。

解決方案:大多數關鍵請求只涉及讀取查詢。為了減輕主機的單點故障風險,我們將這些讀取請求從寫入卸載至副本,確保即使主機宕機,這些請求仍能繼續提供服務。雖然寫入操作仍會失敗,但影響已降低;由於讀取仍然可用,因此不再是 SEV0。

為減輕主機故障,我們以高可用性 (HA) 模式運行主機,並配備熱備機,熱備機是一個持續同步的副本,可隨時接管並處理流量。如果主機出現故障或需要離線維護,我們可以迅速將備用機升級為主機,以盡量減少停機時間。Azure PostgreSQL 團隊已進行大量工作,確保即使在極高負載下,這些故障轉移仍然安全可靠。為了處理讀取副本故障,我們在每個地區部署多個副本,並預留足夠的容量空間,確保單一副本故障不會導致地區性停機。

工作負載隔離

挑戰:我們經常遇到某些請求在 PostgreSQL 實例上消耗不成比例資源的情況。這可能會導致在相同實例上運行的其他工作負載效能下降。例如,在新功能推出時,可能會引入效率低的查詢,導致大量耗用 PostgreSQL CPU,從而拖慢其他關鍵功能的請求。

解決方案:我們在多個地理區域運行近 50 個讀取副本,以盡量減少延遲。然而,根據目前的架構,主機必須將 WAL 串流到每個副本。雖然目前在非常大型的實例類型和高網絡頻寬下仍能良好地擴展,但我們不能無限增加副本,否則最終會令主機超載。為了解決這個問題,我們正與 Azure PostgreSQL 團隊合作進行級聯複製(在新視窗中開啟),中間副本會將 WAL 轉送至下游副本。此方針讓我們有可能擴展至過百個副本,而不會令主機不勝負荷。然而,這亦增加了額外的操作複雜性,尤其是在故障轉移管理方面。此功能仍在測試中;我們會確保其穩健性和能夠安全故障轉移,然後才會在生產階段推行。

postgreSQL 級聯複製圖

速率限制

挑戰:特定端點的流量突然激增、昂貴查詢激增或重試風暴,都可能迅速耗盡 CPU、I/O 和連線等關鍵資源,導致廣泛服務降級。

解決方案:我們在多個層面實施速率限制,包括應用程式、連線池管理器、代理和查詢,以防止突發流量激增令資料庫實例不勝負荷,並觸發級聯故障。避免過短的重試間隔亦同樣同重,這可能會觸發重試風暴。我們亦增強了 ORM 層以支援速率限制,並在必要時完全封鎖特定的查詢摘要。這種針對性的負載卸除方式,能夠從昂貴查詢突然激增中迅速恢復。

結構定義管理

挑戰:即使是小型的結構定義變更,例如更改欄位類型,亦可能觸發整個表格的重寫(在新視窗中開啟)。因此,我們謹慎進行結構定義變更,將其局限於輕量操作,避免任何會重寫整個表格的變更。

解決方案:只允許輕量結構定義變更,例如新增或移除不會觸發完整表格重寫的欄位。我們對結構定義變更執行嚴格的 5 秒超時設定。允許同時建立和刪除索引。結構定義變更僅限於現有表格。如果新功能需要額外的表格,則必須使用替代的分片系統,例如 Azure CosmosDB,而非 PostgreSQL。當回填表格欄位時,我們會施加嚴格的速率限制,防止寫入激增。雖然此流程有時可能需時一週以上,但能夠確保穩定性,避免對生產造成任何影響。

成果與未來方針

這項努力證明只要具備適合的設計與最佳化,Azure PostgreSQL 便可擴展以處理最大規模的生產工作負載。PostgreSQL 可處理寫入量龐大的工作負載的每秒數百萬次查詢,支援 OpenAI 最關鍵的產品,例如 ChatGPT 和 API 平台。我們新增了接近 50 個讀取副本,將複製延遲維持在接近零,並在地理分佈的各個區域保持低延遲讀取,建立了足夠容量空間以支援未來增長。

這種擴展方式在將延遲降至最低的同時,亦能提升可靠性。我們在生產中持續提供低雙位數毫秒的 p99 客戶端延遲,以及 99.999% 的可用性。而在過去 12 個月,我們只發生過一次 SEV-0 PostgreSQL 事件(事件發生於 ChatGPT ImageGen 的病毒式發佈(在新視窗中開啟)期間,當時因超過 1 億名新用戶在一週內註冊,寫入流量突然激增超過 10 倍。)

雖然我們對 PostgreSQL 迄今為止為我們帶來的成果感到滿意,但我們仍會持續推進其極限,確保我們有足夠空間支持未來的增長。我們已經將可分片的寫入量龐大的工作負載遷移到我們的分片系統,例如 CosmosDB。其餘寫入量龐大的工作負載更難分片,我們亦正積極遷移,以進一步卸載從 PostgreSQL 主機的寫入。我們亦正與 Azure 合作,啟用級聯複製,以便我們能安全地擴展至更多讀取副本。

展望未來,隨著我們的基礎設施需求持續增長,我們將繼續探索更多進一步擴展的方案,包括分片 PostgreSQL 或其他分佈式系統。

作者

Bohan Zhang

鳴謝

特別鳴謝 Jon Lee、Sicheng Liu、Chaomin Yu 和 Chenglong Hao 對本文章的貢獻,以及鳴謝協助擴展 PostgreSQL 的整個團隊。我們亦感謝 Azure PostgreSQL 團隊的強大合作夥伴關係。