Hopp til hovedinnhold
OpenAI

22. januar 2026

Teknisk arbeid

Skalere PostgreSQL for støtte til 800 millioner ChatGPT‑brukere.

Av Bohan Zhang, medlem av teknisk stab

Laster inn …

I årevis har PostgreSQL, som driver kjerneprodukter som ChatGPT og OpenAIs API, vært et av de mest kritiske datasystemene i kulissene. Etter hvert som brukerbasen vår vokser raskt, har også kravene til databasene våre økt eksponentielt. I løpet av det siste året har PostgreSQL-belastningen vår tidoblet seg, og den fortsetter å øke raskt.

Våre anstrengelser for å forbedre produksjonsinfrastrukturen vår for å opprettholde denne veksten avdekket en ny innsikt: PostgreSQL kan skaleres for å støtte mye større lesetunge arbeidsbelastninger enn mange tidligere trodde var mulig på en pålitelig måte. Systemet (opprinnelig utviklet av et team av forskere ved University of California, Berkeley) har gjort det mulig for oss å støtte massiv global trafikk med én fleksibel primær Azure PostgreSQL-serverinstans(åpnes i et nytt vindu) og nesten 50 lesereplikaer fordelt på flere regioner globalt. Dette er historien om hvordan vi har skalert PostgreSQL hos OpenAI for å støtte millioner av forespørsler per sekund for 800 millioner brukere gjennom grundige optimaliseringer og solid ingeniørarbeid; vi vil også dele viktige lærdommer vi har fått underveis.

Svake punkter i vår opprinnelige design

Etter lanseringen av ChatGPT økte trafikken i et enestående tempo. For å støtte dette, implementerte vi raskt omfattende optimaliseringer både på applikasjonslaget og i PostgreSQL-databaselaget, oppskalerte ved å øke instansstørrelsen, og utskalerte ved å legge til flere lesereplikaer. Denne arkitekturen har fungert godt i lang tid. Med pågående forbedringer fortsetter det å gi rikelig med muligheter for fremtidig vekst.

Det kan virke overraskende at en enkel primærarkitektur kan møte kravene til OpenAIs skala, men å få dette til å fungere i praksis er ikke enkelt. Vi har sett flere SEV-er forårsaket av overbelastning i Postgres, og de følger ofte det samme mønsteret: et oppstrømsproblem fører til en kraftig økning i databasebelastning, som omfattende hurtigbuffertap fra en feil i hurtigbufferlaget, en plutselig og kraftig økning av kostbare flerveissammenføyninger som metter CPU, eller en skrivestrøm utløst av lanseringen av en ny funksjon. Når ressursutnyttelsen øker, øker spørreforsinkelsen, og forespørsler begynner å utløpe. Gjentatte forsøk forsterker deretter belastningen ytterligere, og utløser en ond sirkel som kan forringe hele ChatGPT- og API-tjenestene.

Skaleringsdiagram for belastning

Selv om PostgreSQL skalerer godt for våre lesetunge arbeidsbelastninger, støter vi fortsatt på utfordringer i perioder med høy skrivetrafikk. Dette skyldes i stor grad PostgreSQLs implementering av mange versjoner for samtidighetskontroll (MVCC), som gjør det mindre effektivt for skriveintensive arbeidsbelastninger. For eksempel, når en forespørsel oppdaterer en tuple eller til og med et enkelt felt, kopieres hele raden for å lage en ny versjon. Ved tung skrivebelastning fører dette til betydelig skriveforsterkning. Det øker også leseforsterkningen, siden forespørslene må skanne gjennom flere tuple-versjoner (døde tupler) for å hente den siste. MVCC introduserer flere utfordringer som oppblåsing av tabeller og indekser, økt ekstra vedlikeholdsbelastning for indekser, og kompleks justering av autovacuum. (Du kan finne en grundig gjennomgang om disse problemene i en blogg jeg skrev sammen med prof. Andy Pavlo ved Carnegie Mellon University kalt The Part of PostgreSQL We Hate the Most(åpnes i et nytt vindu), sitert(åpnes i et nytt vindu) på PostgreSQLs Wikipedia-side.)

Skalering av PostgreSQL til millioner av QPS

For å avhjelpe disse begrensningene og redusere skrivetrykket har vi migrert, og fortsetter å migrere, delbare (dvs. arbeidsbelastninger som kan deles opp horisontalt), skriveintensive arbeidsbelastninger til partisjonerte systemer som Azure Cosmos DB, og optimalisering av applikasjonslogikk for å minimere unødvendige skrivinger. Vi tillater heller ikke lenger å legge til nye tabeller i den nåværende PostgreSQL-distribusjonen. Nye arbeidsbelastninger har som standard partisjonerte systemer.

Selv om infrastrukturen vår har utviklet seg, har PostgreSQL forblitt udelt, med én primær instans som håndterer alle skrivinger. Den primære begrunnelsen er at partisjonering av eksisterende applikasjonsarbeidsbelastninger vil være svært komplekst og tidkrevende, og kreve endringer i hundrevis av applikasjonsendepunkter, noe som potensielt kan ta måneder eller til og med år. Siden arbeidsbelastningene våre hovedsakelig er lesetunge, og vi har gjennomført omfattende optimaliseringer, gir den nåværende arkitekturen fortsatt god kapasitet til å støtte videre trafikkvekst. Selv om vi ikke utelukker partisjonering av PostgreSQL i fremtiden, er det ikke en prioritet på kort sikt, gitt at vi har tilstrekkelig handlingsrom for nåværende og fremtidig vekst.

I de følgende avsnittene vil vi fordype oss i utfordringene vi møtte, og de omfattende optimaliseringene vi implementerte, for å håndtere dem og forhindre fremtidige avbrudd, ved å presse PostgreSQL til det ytterste og skalere det til millioner av forespørsler per sekund (QPS).

Redusere belastningen på primærnoden

Utfordring: Med bare én skriver kan ikke et oppsett med én primærnode skalere skriveoperasjoner. Kraftige skrivetopper kan raskt overbelaste primærnoden og påvirke tjenester som ChatGPT og vår API.

Løsning: Vi minimerer belastningen på primærnoden så mye som mulig–både lesing og skriving–for å sikre at den har tilstrekkelig kapasitet til å håndtere plutselige økninger i skrivetopper. Lesetrafikk flyttes til replikaer der det er mulig. Noen lesesforespørsler må imidlerti forbli på primærnoden fordi de er en del av skrivetransaksjoner. For disse fokuserer vi på å sikre at de er effektive og unngår trege forespørsler. For skrivetrafikk har vi migrert delbare, skrivetunge arbeidsbelastninger til delte systemer som Azure CosmosDB. Arbeidsbelastninger som er vanskeligere å dele opp, men som fortsatt genererer et høyt skrivevolum, tar lengre tid å migrere, og den prosessen pågår fortsatt. Vi optimaliserte også applikasjonene våre aggressivt for å redusere skrivebelastningen. Vi har for eksempel korrigert applikasjonsfeil som forårsaket overflødige skrivinger og innført forsinket skriving, der det er hensiktsmessig, for å jevne ut trafikktopper. I tillegg håndhever vi strenge bruksgrenser når vi fyller ut tabellfelt, for å forhindre for høyt skrivettrykk.

Spørreoptimalisering

Utfordring: Vi identifiserte flere kostbare forespørsler i PostgreSQL. Tidligere førte plutselige volumtopper i disse spørringene til høyt CPU-forbruk, noe som gjorde både ChatGPT og API-forespørsler tregere.

Løsning: Noen få kostbare spørringer, som de som kobler sammen mange tabeller, kan fottinge ytelsen betydelig eller til og med ta ned hele tjenesten. Vi må kontinuerlig optimalisere PostgreSQL-spørringer for å sikre at de er effektive, og unngå vanlige inneffektive løsninger i Online Transaction Processing (OLTP). Vi identifiserte for eksempel én gang en ekstremt kostbar spørring som koblet sammen 12 tabeller, der topper i denne spørringen var ansvarlige for tidligere SEV-er med høy alvorlighetsgrad. Vi bør unngå komplekse sammenføyninger på tvers av mange tabeller der det er mulig. Hvis sammenføyninger er nødvendige, lærte vi å vurdere oppdelinger av spørringen, og i stedet flytte kompleks sammenføyningslogikk til applikasjonslaget. Mange av disse problematiske spørringene genereres av Object-Relational Mapping-rammeverk (ORM-er). Det er derfor viktig å nøye gjennomgå SQL-en de produserer og sikre at den oppfører seg som forventet. Det er også vanlig å finne langvarige, inaktive spørringer i PostgreSQL. Konfiguteting av tidsavbrudd som idle_in_transaction_session_timeout er viktig for å hindre at de blokkerer autovacuum (automatisk opprydding).

Tiltak mot enkeltpunktsfeil

Utfordring: Hvis en lesereplika går ned, kan trafikk fortsatt dirigeres til andre replikaer. Men å være avhengig av én skriver innebærer et enkeltpunktsfeil–hvis det svikter, blir hele tjenesten påvirket.

Løsning: De mest kritiske forespørslene innebærer kun lesesforespørsler. For å redusere risikoen for et enkelt feilpunkt i primærnoden, avlastet vi disse leseoperasjonene fra skriveren til replikaer, slik at disse forespørslene fortsatt kan bli betjent selv om primærnoden går ned. Selv om skriveoperasjoner fortsatt ville mislykkes, er konsekvensene redusert. Det er ikke lenger en SEV0 siden lesing fortsatt er tilgjengelig.

For å redusere konsekvensene av feil på primærnoden, kjører vi primærnoden i høy tilgjengelighet (HA) med en varm standby, en kontinuerlig synkronisert replika som alltid er klar til å overta trafikken. Hvis primærnoden går ned, eller må tas offline for vedlikehold, kan vi raskt oppgradere standby for å minimere nedetid. Azure PostgreSQL-teamet har utført betydelig arbeid for å sikre at disse failoverne forblir trygge og pålitelige selv under svært høy belastning. For å håndtere feil i lesereplikaer, distribuerer vi flere replikaer i hver region med tilstrekkelig kapasitetsmargin, slik at en enkelt replikafeil ikke fører til et regionalt driftsavbrudd.

Isolering av arbeidsmengde

Utfordring: Vi støter ofte på situasjoner der enkelte forespørsler bruker en uforholdsmessig stor mengde ressurser på PostgreSQL-instanser. Dette kan føre til redusert ytelse for andre arbeidsbelastninger som kjører på de samme instansene. Lansering av en ny funksjon kan for eksempel føre til ineffektive forespørsler som i stor grad belaster PostgreSQL CPU, noe som gjør forespørsler for andre viktige funksjoner tregere.

Løsning: Vi opererer nesten 50 lesereplikaer på tvers av flere geografiske regioner for å minimere ventetid. Imidlertid må primærnoden med den nåværende arkitekturen strømme WAL til hver replika. Selv om den for øyeblikket skalerer godt med svært store instanstyper og høy nettverksbåndbredde, kan vi ikke fortsette å legge til replikaer i det uendelige uten å til slutt overbelaste primærnoden. For å løse dette samarbeider vi med Azure PostgreSQL-teamet om trinnvis replikering(åpnes i et nytt vindu), der mellomliggende replikaer videresender WAL til nedstrøms replikaer. Denne tilnærmingen lar oss skalere til potensielt over hundre replikaer uten å overbelaste primærnoden. Det introduserer imidlertid også ytterligere operasjonell kompleksitet, særlig rundt failoverhåndtering. Funksjonen er fortsatt under testing, og vi vil sørge for at den er robust og kan håndtere feil på en trygg måte før vi utruller den til produksjon.

En rekke PostgreSQL-replikasjonsdiagram

Hastighetsbegrensning

Utfordring: En plutselig trafikkøkning på spesifikke endepunkter, en økning i kostbare forespørsler eller en overbelastning fra gjentatte kan raskt tømme kritiske ressurser som CPU, I/O og tilkoblinger, noe som forårsaker omfattende tjenesteforringelse.

Løsning: Vi implementerte hastighetsbegrensning på tvers av flere lag–applikasjon, gjenbruksordning for tilkoblinger, proxy og forespørsel–for å forhindre at plutselige trafikktopper overbelaster databaseinstanser og utløser kjedereaksjoner av feil. Det er også viktig å unngå for korte forsøksintervaller, da dette kan utløse overbelastning fra gjentatte forsøk. Vi forbedret også ORM-laget for å støtte hastighetsbegrensning, og når det er nødvendig, blokkere spesifikke oppsummeringer av forespørsler. Denne målrettede formen for belastningsbegrensning muliggjør rask gjenoppretting fra plutselige økninger i kostbare forespørsler.

Skjemaadministrasjon

Utfordring: Selv en liten skjemaendring, som å endre en kolonnetype, kan utløse en full omskriving av tabellen(åpnes i et nytt vindu). Derfor bruker vi skjemaendringer med varsomhet – vi begrenser dem til lette operasjoner og unngår alle som omskriver hele tabeller.

Løsning: Kun endringerav lettvektskjema er tillatt, som å legge til eller fjerne enkelte kolonner som ikke utløser en fullstendig omskriving av tabellen. Vi håndhever streng et 5-sekunders tidsavbrudd for endringer i skjemaet. Det er tillatt å opprette og fjerne indekser samtidig. Skjemaendringer er begrenset til eksisterende tabeller. Hvis en ny funksjon krever flere tabeller, må de være i alternative partisjonerte systemer som Azure CosmosDB i stedet for PostgreSQL. Når vi fyller ut et tabellfelt, bruker vi strenge bruksgrenser for å forhindre skrivetopper. Selv om denne prosessen noen ganger kan ta over en uke, sikrer den stabilitet og unngår påvirkning på produksjonen.

Resultater og veien videre

Denne innsatsen viser at med riktig design og optimaliseringer, kan Azure PostgreSQL skaleres for å håndtere de største produksjonsarbeidsbelastningene. PostgreSQL håndterer millioner av QPS for lesetunge arbeidsbelastninger, og driver OpenAIs mest kritiske produkter som ChatGPT og API-plattformen. Vi la til nesten 50 lesereplikaer, samtidig som vi holdt replikeringsforsinkelsen nær null, opprettholdt lav forsinkelse av lesinger på tvers av geografisk distribuerte regioner, og bygde tilstrekkelig kapasitetsmargin for å støtte fremtidig vekst.

Denne skaleringen fungerer mens den minimerer ventetiden og forbedrer påliteligheten. Vi leverer konsekvent p99-forsinkelse i et lavt tosifret antall millisekunder og fem-niers (99,999 %) tilgjengelighet i produksjon. Og i løpet av de siste 12 månedene har vi hatt bare én SEV-0 PostgreSQL-hendelse (den skjedde under viral lansering(åpnes i et nytt vindu) av ChatGPT ImageGen, da skrivetrafikken plutselig økte med mer enn 10x, fordi over 100 millioner nye brukere registrerte seg i løpet av én uke.)

Selv om vi er fornøyde med hvor langt PostgreSQL har tatt oss, fortsetter vi å presse grensene for å sikre at vi har tilstrekkelig handlingsrom for fremtidig vekst. Vi har allerede migrert de delbare, skrivetunge arbeidsbelastningene til våre delte systemer som CosmosDB. De gjenværende skriveintensive arbeidsbelastningene er mer utfordrende å dele opp–vi migrerer også disse aktivt for å avlaste PostgreSQL-primærnoden ytterligere for skriveroperasjoner. Vi samarbeider også med Azure for å muliggjøre en rekke replikering, slik at vi trygt kan skalere til betydelig flere lesereplikaer.

Når vi ser fremover, vil vi fortsette å utforske flere tilnærminger for å skalere ytterligere, inkludert partisjonert PostgreSQL eller alternative distribuerte systemer, ettersom infrastrukturbehovene våre fortsetter å vokse.

Forfatter

Bohan Zhang

Anerkjennelser

En spesiell takk til Jon Lee, Sicheng Liu, Chaomin Yu og Chenglong Hao, som bidro til dette innlegget, og til hele teamet som hjalp til med å skalere PostgreSQL. Vi vil også takke Azure PostgreSQL-teamet for deres sterke partnerskap.