所有 OpenAI 產品都需要快速、可靠地存取資料,這由我們的儲存平台 Habitat 提供。它必須在幾毫秒內回應來自 40 個地理區域、超過 10 億用戶的請求。我們的基礎設施面臨著一項非凡的挑戰:在持續提升可靠性、效能和產品開發人員速度的同時,支援爆炸性成長和新的使用案例。
解決這項挑戰需要重新思考我們的線上儲存平台是如何設計和運作的。我們不斷評估權衡,遵循以下模式:首先達到足以處理關鍵產品流量的可靠性,然後達到足以服務全球用戶的速度,最後才能在大規模下靈活運作。
這篇文章是系列報導的第二部分,深入探討 OpenAI 如何擴展其線上儲存平台 Habitat 的底層元件 Azure Cosmos DB。為服務全球逾十億 ChatGPT 用戶,OpenAI 與 Azure 團隊緊密合作,從單租戶系統轉向共管的多租戶容器,成功解決了大規模資料存取與效能挑戰。文章詳述了他們在擴展過程中遇到的問題,以及如何透過與 Azure 合作開發新功能來克服這些困難。

所有 OpenAI 產品都需要快速、可靠地存取資料,這由我們的儲存平台 Habitat 提供。它必須在幾毫秒內回應來自 40 個地理區域、超過 10 億用戶的請求。我們的基礎設施面臨著一項非凡的挑戰:在持續提升可靠性、效能和產品開發人員速度的同時,支援爆炸性成長和新的使用案例。
解決這項挑戰需要重新思考我們的線上儲存平台是如何設計和運作的。我們不斷評估權衡,遵循以下模式:首先達到足以處理關鍵產品流量的可靠性,然後達到足以服務全球用戶的速度,最後才能在大規模下靈活運作。
這個兩部分系列解釋了我們如何將 Habitat 從一個簡單的客戶端函式庫和資料庫,發展成一個服務超過 500 PB 資料的全球分散式儲存平台。第一部分著重於 Habitat 從 Python 客戶端到服務的演變,並涵蓋了我們如何將基於 Python 的服務推向許多人認為不切實際的極限。
在這篇文章(第二部分)中,我們將探討如何擴展底層儲存元件:Azure Cosmos DB。透過與 Azure 團隊的密切合作,我們找到了一種可行的共管容器多租戶方法,在大規模全球範圍內實現了卓越的讀取效能。
圖 01 · 什麼是 Habitat?
線上儲存平台
Habitat 是我們建立的線上儲存平台,讓 OpenAI 產品能夠快速可靠地存取所需資訊。
請求
回應
變更資料擷取 (CDC)
隨著公司規模擴大,基礎設施團隊通常會從運行單租戶系統轉向多租戶系統。單租戶模式下,每個產品介面團隊維護自己的系統,這可以減少影響範圍,並提供明確的所有權界限和工作負載隔離。然而,隨著團隊和產品介面的增長,這種模式的運行成本會變得很高。單租戶模式讓每個產品團隊負責容量規劃,並經常導致顯著的資源過度配置。
相反地,多租戶模式將控制權交給中央資料庫團隊,他們擁有更好的資源配置知識和經驗。但多租戶模式也會產生自己的問題,例如「吵雜鄰居」問題,即一個租戶消耗了異常大量的資源,從而損害了其他租戶的效能。
在 Habitat 中,我們必須權衡所有這些因素,以設計一個可靠、高效且大規模的儲存系統。如今,Habitat 是許多 OpenAI 產品的多租戶資料庫層,但我們經歷了一個循環的旅程:從使用一個多租戶 Azure Cosmos DB 容器,到配置單租戶後端容器,再預設回歸到多租戶容器。
我們在 Habitat 上的多租戶故事仍處於早期階段:我們支援大量使用案例,但透過盡可能利用 Azure Cosmos DB 的內建原語,我們得以推遲在這一領域的投資。
在深入探討我們的 Azure Cosmos DB 旅程之前,先提供一些基本背景資訊:
一個 Azure Cosmos DB 帳戶定義了一組容器和一個複製策略。
每個容器都配置了特定數量的每秒請求單位 (RU/s) 吞吐量。
每個容器內的資料以典型的「按指定邏輯分割區鍵分片」方式儲存,並有文件記載的每個邏輯分割區鍵的儲存和吞吐量限制。
Azure Cosmos DB 負責將邏輯分割區鍵分片到較少的後端實體分割區,當儲存超過閾值或容器需要更多實體分割區來維持配置的吞吐量時,會將它們分割成多個實體分割區。
我們最初允許任何客戶端負載通過,並依賴每個邏輯分割區鍵 10K RU/s 的限制來提供背壓。最初,我們每個帳戶也只使用一個預設的 Azure Cosmos DB 容器。這運作得相當好,但由於幾個原因證明存在問題:
由於早期的 API 選擇,我們將邏輯分割區鍵的選擇直接暴露給客戶端。因此,我們經常在不同產品使用案例中,於常用分割區鍵(例如 user_id 或 workspace_id)上發生衝突。由於這些使用案例共享相同邏輯分割區鍵的 Azure Cosmos DB 限制,此設計限制了特定用戶的整體吞吐量。
在我們轉移到 Habitat 和 Azure Cosmos DB 之前,擴展 Postgres 時面臨的一個常見問題是,來自一個非常熱門的組織或熱門鍵(即一個租戶產生不成比例的高負載)的許多請求可能會導致整個資料庫癱瘓。我們投入了大量的集體努力來快取這些鍵,並在快取未命中時建立租約,以確保由此產生的快取未命中負載不會壓垮底層資料庫。
圖 02a · 邏輯分割區鍵限制
不同的客戶端,相同的分割區鍵
雖然文件記載的資料大小和吞吐量限制適用於邏輯分割區鍵,但實際執行限制的是實體分割區。實際上,這意味著邏輯分割區無法達到 10,000 RU/s。相反地,它們與位於同一實體分割區上的所有其他邏輯分割區鍵共享實體分割區的限制。
這使得「吵雜鄰居」能夠影響許多不相關的邏輯分割區鍵,例如針對小眾產品功能的工作負載可能會干擾核心登入和註冊流程。
圖 02b · 吵雜鄰居
不同的用戶,相同的實體分割區
特定實體分割區的吞吐量限制也是可變的,取決於分配給 Azure Cosmos DB 容器的總吞吐量。容器的配置吞吐量大致平均分配給該容器的實體分割區。
隨著資料量的增長,實體分割區會分裂,增加總分割區數量,而總配置吞吐量保持不變。結果是,隨著資料大小的增長,每個分割區的有效吞吐量限制會縮小。
對於我們儲存量最大、類似 blob 的使用案例,這會產生一種故障模式:即使請求率和使用量保持穩定,僅僅儲存量的增長也會降低活躍工作負載的吞吐量容量。
圖 02c · 弱分割區
限制低於需求
當分割區達到其儲存限制時會分裂。每個子分割區獲得一半的吞吐量容量。
獨立容器有助於部分解決這些分割區鍵限制和「吵雜鄰居」問題。透過使用獨立容器,每個容器都可以分配自己的獨立實體分割區,並且只有該容器上變動的工作負載才會成為「吵雜鄰居」或在分割區鍵空間中重疊。缺點是,配置新容器會產生非零的開銷,每個容器都需要個別的容量規劃,因此我們希望僅在有意義的服務或使用案例邊界處建立容器。
我們開始為最關鍵、需要強隔離的新使用案例使用獨立的 Azure Cosmos DB 容器。結合一個透過同步每個容器的總配置吞吐量與其實體分割區數量來管理弱分割區的腳本,我們大部分避免了之前面臨的所有問題。
然而,由於我們是從預設容器開始的,許多舊有的關鍵使用案例不幸地被困在那裡,無法進行資料遷移。為了保護仍依賴共享預設容器中資料的關鍵服務,我們經常建議團隊為新服務或主要產品功能建立獨立容器。隨著我們規模的擴大,預設容器的壓力增加,生產事故也隨之增多。我們開始為任何新服務或大型產品功能配置容器,僅為了保護預設容器免受更多負載。
這使我們避免了許多全站範圍的停機,將影響範圍限制在功能或服務降級的停機。然而,配置新容器的開銷最終困擾了我們:
在舊的共享預設容器中,任何特定新使用案例從 0 QPS 增長到 100 萬 QPS,都不太可能顯著改變總體聚合使用量。然而,在隔離的容器上,一個新使用案例從 0 增長到 100 萬 QPS,可能代表比僅內部測試的基準負載高出 1,000 倍。
有了專用容器,團隊現在需要記住預先為其發布的容器配置預期的吞吐量水平。產品團隊經常將其功能發布到生產環境,卻忘記預先擴展,我們會在發布當天坐在 SEV 會議室裡,試圖在最後一刻擴展容器。
這是多租戶系統的核心工作負載混合優勢,我們為了更好的隔離而採用這種容器策略時所失去的。
圖 03 · 缺乏穩定的聚合增長
相同的工作負載,不同的餘裕
負載測試期間 1K RU/s → 發布時 1M RU/s
隨著時間的推移,監控專用容器的使用情況也需要對流量何時會轉變或增長有深入的產品知識。
我們可以提供一個基本的控制平面腳本,根據增長趨勢擴展每個容器的配置吞吐量,但由於缺乏穩定的聚合增長,正確擴展這些容器實際上需要 OpenAI 的每個產品團隊都參與容量規劃。
這在組織上無法擴展,因為每個服務的擁有團隊對其 Azure Cosmos DB 配置的勤勉程度差異很大。
隨著組織的發展,這些操作問題變得難以擴展。沒有一個獨立的中央團隊進行規劃,導致許多團隊規劃不善。因此,我們最終轉向多租戶解決方案,並與 Azure 團隊密切合作,為我們最初的多租戶問題設計修復方案,採用共享租戶設計:
首先對最熱門的鍵進行節流,可以防止「吵雜鄰居」消耗特定實體分割區的所有可用吞吐量。這減少了「吵雜鄰居」效應,即一個熱門鍵可能導致全站範圍的影響。
請求分層服務品質 (QoS) 同樣可以防止離線工作負載(例如批量插入或資料提取)利用特定實體分割區的所有吞吐量。透過為這些工作負載的請求分配較低的優先級,它們會首先被節流,從而防止對服務終端用戶的較高優先級、互動式請求進行節流。
Azure Cosmos DB 已經有一個無伺服器模式,可以解決我們在配置模式下的弱分割區問題。然而,它有一個主要缺點:它僅根據儲存使用量進行擴展,並將 RU 使用量限制為每個實體分割區 5K RU/s。這將解決我們的弱分割區問題,但會阻止我們擴展 RU 密集型使用案例。
Azure Cosmos DB 團隊為我們建立的一個新的改進型無伺服器模式,允許每個實體分割區擴展到 10K RU/s,並引入了基於 RU 使用量的分割,除了基於儲存使用量的分割之外,這使我們能夠停止手動監控和擴展容器。
透過這些改變,我們得以重新轉向使用一個共享容器,這顯著簡化了產品團隊進行任何前期或持續容量規劃的需求,同時保持了工作負載之間的隔離。儘管產品開發加速,但在過去幾個月中,我們沒有發生任何配置或「吵雜鄰居」事件。
當公司發展到 OpenAI 的規模時,託管服務變得不那麼「託管」了。許多工作負載在雲端供應商的基礎設施中成為異類。隨著 OpenAI 成為 Azure Cosmos DB 最大的用戶之一,成功運營它需要一種不同的模式:共享測試、共享儀表板、直接工程通道和聯合所有權。
覺得值得一看?分享給朋友。
以上為 AI 自動翻譯導讀。原文版權歸 OpenAI Blog 所有, 建議透過「閱讀原文」前往原始網站,以取得最完整資訊並支持原作者。
43 個來源、每 2 小時更新,太多看不完。電子報每週挑最值得看的幾則,附上 Max 的看法。