- OpenAI hat seine PostgreSQL-Infrastruktur massiv ausgebaut, um auf den starken Anstieg bei ChatGPT- und API-Traffic zu reagieren, und verarbeitet mit einem einzelnen Azure PostgreSQL Flexible Server und rund 50 Read Replicas mehrere Millionen QPS
- Bei Beibehaltung einer auf leselastige Workloads optimierten Architektur wurden zur Entlastung der Schreiblast einige Workloads nach Azure Cosmos DB migriert
- Mit verschiedenen Optimierungen wie PgBouncer Connection Pooling, Cache Locking, Rate Limiting und Workload-Isolierung wurden Stabilität und Latenz verbessert
- Um die Grenzen einer Single-Primary-Architektur zu überwinden, wurden parallel Hochverfügbarkeitskonfigurationen (HA), Hot Standby und Tests mit Cascading Replication durchgeführt
- Mit diesem Ansatz wurden 99,999 % Verfügbarkeit und p99-Latenzen im zweistelligen Millisekundenbereich erreicht; zugleich wurde die Grundlage für eine künftige Skalierung mit sharded PostgreSQL oder verteilten Systemen geschaffen
Überblick über die PostgreSQL-Skalierung
- PostgreSQL ist das zentrale Datensystem für ChatGPT und die OpenAI API; in den vergangenen 12 Monaten ist die Last um mehr als das Zehnfache gestiegen
- Mit einer einzelnen Primary-Instanz und weltweit verteilten rund 50 Read Replicas werden die Anfragen von 800 Millionen Nutzern verarbeitet
- Bei Beibehaltung der leselastigen Struktur wurden einige Workloads zur Entlastung der Schreiblast nach Azure Cosmos DB verlagert
- Das Hinzufügen neuer Tabellen ist untersagt, und neue Workloads werden standardmäßig in einem Sharding-System platziert
Herausforderungen und Gegenmaßnahmen bei einer Single-Primary-Architektur
- Eine Single-Writer-Architektur hat Grenzen bei der Schreibskalierung und ein Single Point of Failure (SPOF)
- Lesetraffic wird auf Replicas verteilt, Schreibtraffic für shardbare Workloads wurde nach Cosmos DB verlagert
- Eine Hochverfügbarkeitskonfiguration mit Hot Standby unterstützt im Fehlerfall eine schnelle Promotion (Failover)
- Bei sprunghaft ansteigender Leselast kam es durch eine Welle von Cache Misses zu CPU-Sättigung
- Durch Einführung eines Cache-Locking-Mechanismus werden doppelte Abfragen für denselben Schlüssel verhindert
Abfrage- und Ressourcenoptimierung
- Komplexe Multi-Join-Abfragen belegten übermäßig viel CPU und verursachten Service-Latenzen
- Ineffizientes, vom ORM erzeugtes SQL wurde überprüft, und komplexe Join-Logik wurde in die Anwendungsschicht verlagert
- Mit der Einstellung idle_in_transaction_session_timeout werden lang andauernde inaktive Abfragen verhindert
- Zur Lösung des „Noisy Neighbor“-Problems wurde Traffic auf Instanzen nach Priorität getrennt
- Niedrig priorisierte Anfragen werden isoliert, damit sie hoch priorisierte Services nicht beeinträchtigen
Verbindungsmanagement und Laststeuerung
- Um das Limit von 5.000 Verbindungen bei Azure PostgreSQL zu überwinden, wurde PgBouncer als Proxy-Schicht eingeführt
- Durch Wiederverwendung von Verbindungen wurde die durchschnittliche Verbindungszeit von 50 ms auf 5 ms reduziert
- Um regionenübergreifende Netzwerklatenzen zu verringern, wurden Proxy, Client und Replica in derselben Region platziert
- Rate Limiting wurde auf Anwendungs-, Proxy- und Abfrageebene angewendet, um plötzliche Traffic-Spitzen zu verhindern
- Auch die ORM-Schicht wurde so verbessert, dass bestimmte Query Digests blockiert werden können
Replikation und Management von Schemaänderungen
- Da die Primary WAL-Logs an alle Replicas streamen muss, steigt bei wachsender Zahl von Replicas die Netzwerklast
- Cascading Replication wird in Zusammenarbeit mit dem Azure-Team getestet
- Zwischen-Replikas leiten WAL an nachgelagerte Replicas weiter und schaffen damit die Grundlage für eine Skalierung auf mehr als 100 Replicas
- Schemaänderungen, die ein full table rewrite auslösen, sind untersagt
- Innerhalb eines 5-Sekunden-Timeouts sind nur leichte Änderungen erlaubt; das Erstellen und Löschen von Indizes kann gleichzeitig erfolgen
- Auch beim Backfill gelten strenge Geschwindigkeitsbegrenzungen
Ergebnisse und weitere Pläne
- PostgreSQL verarbeitet mehrere Millionen QPS und erreicht Latenzen im Bereich von einigen Dutzend Millisekunden (p99) sowie eine Verfügbarkeit von 99,999 %
- In den vergangenen 12 Monaten gab es nur einen einzigen SEV-0-Vorfall, der beim Launch von ChatGPT ImageGen auftrat
- Die verbleibenden schreiblastigen Workloads werden schrittweise ebenfalls nach Cosmos DB migriert
- Nach Abschluss von Cascading Replication sollen Skalierbarkeit und Stabilität der Replicas weiter verbessert werden
- Künftig wird die Einführung von sharded PostgreSQL oder alternativen verteilten Systemen geprüft
1 Kommentare
Hacker-News-Kommentare
In PostgreSQL verursachen lange laufende idle Queries oft Probleme.
In unserer Codebasis gab es viele Muster wie „connect → Transaktion starten → Arbeit ausführen → bei Erfolg commit“.
Dieser Ansatz belegte dauerhaft Connection-Slots, selbst wenn die Datenbank tatsächlich gar nicht genutzt wurde, sodass wir am Ende die Anzahl der Postgres-Verbindungen auf mehrere Tausend erhöhen mussten.
Deshalb haben wir im Rust-Code eine Compile-Time-Prüfung ergänzt, damit der Compiler sofort warnt, wenn in einer Async-Funktion
.awaitaufgerufen wird, während noch eine Verbindung gehalten wird.Wir haben über 100 Stellen korrigiert, aber dadurch werden Lasttests jetzt auch mit einem Pool von 32 statt 10.000 Verbindungen nicht langsamer.
Ein einfach kürzeres idle timeout wäre ebenfalls eine Möglichkeit gewesen, aber die statische Prüfung war eine deutlich verlässlichere Lösung.
Der Artikel wirkte zu oberflächlich und wiederholte nur Schlagwörter wie „wir haben sharding gemacht!“.
Es gab kaum Details, und vieles las sich wie SEO-Text.
Die Kernaussage des Artikels lässt sich etwa so zusammenfassen: „Ein einzelner writer skaliert nicht, also haben wir Schreibvorgänge reduziert und Lesezugriffe getrennt.“
Wirklich Neues gab es kaum, erwähnt wurden nur die üblichen Ansätze wie Query-Optimierung, Sharding und Read Replicas.
Ich mag Postgres vor allem deshalb, weil man allein durch mehr CPU und mehr Storage schon ziemlich weit skalieren kann.
An diesem Punkt kann man sich dann auch Sharding-Experten leisten.
Deshalb klingt die Aussage „für Sharding muss man Postgres verlassen“ etwas seltsam.
OpenAI macht zum Beispiel selbst jetzt noch enorme Verluste, und laut Berichten ist unklar, ob das Unternehmen bis 2027 durchhält.
Beim Thema Schema-Änderungen und Timeouts wurde angemerkt, dass nicht nur Timeout-Einstellungen helfen:
Wenn man während eines Schema-Rollouts parallel ein Skript zum automatischen Beenden kollidierender Transaktionen laufen lässt, ist das deutlich effizienter.
Es wäre gut, wenn Postgres so etwas standardmäßig anbieten würde — statt unter schweren Locks zu warten, ist es oft besser, einige Transaktionen abzubrechen.
Es war interessant, dass dies der erste Beitrag im OpenAI-Engineering-Blog war.
Hoffentlich folgen weitere Praxisbeispiele.
Interessant war auch die Frage nach der Replikationskonfiguration.
Es hieß, man habe mit 50 Read Replicas kaum Replikationsverzögerung gesehen,
dabei ist in der Praxis gut möglich, dass einzelne Replicas durch CPU- oder Memory-Spitzen zurückfallen.
Dann könnte auch der Primary durch Warten auf die WAL-Übertragung langsamer werden.
Es gab die Aussage, dass neue Features, die zusätzliche Tabellen benötigen, nicht in PostgreSQL, sondern in Azure CosmosDB abgelegt werden.
Das wirkte so, als lasse man das bestehende System unverändert und verlagere nur neue Funktionen in eine andere Datenbank.
Es wurde erwähnt, dass man „die Instanzgröße erhöht“ habe, aber wie weit genau, blieb offen.
Interessant wäre gewesen, welche CPU- und RAM-Ausstattung verwendet wurde, ob das normale Instanzen wie für gewöhnliche Nutzer sind oder kundenspezifische Hardware.
Beispiel: Azure Standard_E192ibds_v6 (96 Kerne, 1,8 TB RAM, 10 TB SSD, 3M IOPS).
Noch größere Modelle gibt es etwa für SAP HANA, zum Beispiel Standard_M896ixds_24_v3 mit 896 Kernen, 32 TB Speicher und 185 Gbit/s Netzwerk.
Solche Maschinen kosten rund 175.000 Dollar im Monat, aber OpenAI hat vermutlich massive Rabatte erhalten.
Persönlich würde ich für einen Datenbankserver lieber eine HPC-VM wie HX176rs verwenden.
Dank HBM-Cache ist der Memory-Durchsatz deutlich höher, und die Leistung war viel besser als bei normalen VMs in ähnlicher Preisklasse.
Azure PostgreSQL zusammen mit CosmosDB zu betreiben dürfte extrem teuer sein.
Trotzdem war dieser Artikel eine der realistischeren Beschreibungen davon, wie man PostgreSQL skaliert.
Ohne Kernel-Patches oder Hacks am Source Code, sondern in einer Standard-Cloud-Umgebung — das wirkte nachvollziehbar.