0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ChatGPTの8億ユーザーは「単一PostgreSQLプライマリ」で動いている

0
Posted at

きっかけ

X でこんな趣旨のポストを見かけました。

ChatGPTは8億人のユーザーを単一のPostgreSQLプライマリで処理している。読み取りは約50台のレプリカに分散し、書き込みの重い処理は Cosmos DB へ逃がし、PgBouncer とキャッシュロックとレート制限でプライマリを保護。結果として 99.999% の可用性を達成した。

元ポスト: https://x.com/kuwa_tw/status/2115789385170104487
(リンク先は Hashnode のまとめ記事: https://mahmad.hashnode.dev/chatgpt-800-million-users-one-postgres-primary )

「単一プライマリで8億人」はさすがに盛ってないか、と思って公式ブログを辿ったメモです。

公式ブログの確認

この話の出どころは、OpenAI のインフラエンジニア Bohan Zhang による公式ブログ 「Scaling PostgreSQL to power 800 million ChatGPT users」(2026年1月公開)でした。VentureBeat など複数メディアも報じていて、主要な数字は二次情報とも一致しています。

  • 構成: Azure PostgreSQL Flexible Server の 単一プライマリ(書き込み)+ 約50台のリードレプリカ(読み取り)、シャーディングなし
  • 規模: 約8億ユーザー、数百万 QPS、p99 は低い二桁ミリ秒、可用性 99.999%
  • PostgreSQL の負荷は1年で10倍以上に増加
  • この1年で大きな障害は1回だけ(画像生成ブームで書き込みが平常の10倍超に跳ねたとき)

つまりポストの要約は、盛っているわけではなく公式ブログどおりでした。

なぜシャーディングしないのか

まず言葉の整理です。シャーディング とは、DB を複数台に分けてデータを分散させること。たとえば「ユーザーID が偶数の人は DB1、奇数の人は DB2」のように分けて、1台あたりの負荷を下げます。

規模が大きくなればシャーディングが定石に見えますが、OpenAI はあえて選びませんでした。理由は現実的なコストの問題です。

今の ChatGPT のコードは、数百あるエンドポイント(API)が「1つの DB を見れば、必要なデータは全部そこにある」前提で書かれています。たとえば「ユーザー情報と、その人の会話履歴を JOIN して取る」ような処理が当たり前にできます。

これをシャーディングすると、その前提が崩れます。

  • データが別々の DB に散るので、DB をまたいだ JOIN ができなくなる
  • 「このデータはどちらの DB に聞けばいいか」という振り分けが全処理に必要になる
  • 複数の DB にまたがる更新で、データの整合性を保つのが難しくなる

つまり数百の API を「データの場所を意識する作り」に書き直すことになり、数ヶ月規模の大工事と、バグが入り込むリスクを引き受けることになります。

代わりに取った方針は、全部を分割する大手術ではなく、問題を切り分けて、痛いところだけ外に出す ことでした。

  • 書き込みが重くて分割しやすいワークロードは Azure Cosmos DB へ移行
  • この PostgreSQL には 新規テーブルを追加しない ルールにした(新しいものは最初からシャーディング前提の基盤へ)

Azure Cosmos DB とは
Microsoft のクラウド DB です。PostgreSQL のような表形式(リレーショナル)ではなくドキュメント型の NoSQL で、最初から複数台へデータを分散する(シャーディングする)設計のため、書き込みを水平にスケールさせやすいのが特徴です。

OpenAI は、PostgreSQL が苦手な「重い書き込み」をこの Cosmos DB に任せ、読み取り中心の本体は PostgreSQL に残す、という適材適所の役割分担をしています。

プライマリを守るための施策

単一プライマリ構成が成り立つのは、プライマリに余計な負荷を一切かけない運用があるからでした。

  • 読み取りのオフロード: 読み取りはレプリカへ寄せ、その手前にキャッシュ層を置いて大半の読み取りを DB に到達させない
  • PgBouncer で接続プーリング: 平均接続時間が 50ms → 5ms に短縮
  • キャッシュロックでスタンピード防止: キャッシュの有効期限切れで一斉に DB へアクセスが殺到する(thundering herd)現象を、ロックで1リクエストだけに代表させる
  • 多層のレート制限とワークロード分離: アプリ → プーラー → プロキシ → クエリの各層で制限し、優先度の低いバッチやバックフィルはレートを絞る
  • 重いクエリの排除: 重い JOIN などを避ける運用でプライマリを保護

読み書き分離という意味では CQRS の親戚

ここまでの話は、「書き込みと読み取りを分けて、それぞれに最適化する」という点で、CQRS(Command Query Responsibility Segregation)という設計パターンと発想が共通しています。

ただし厳密な CQRS は、書き込み側のモデルと読み取り側のモデル自体を分離し、読み取り用に整形したデータをイベント経由で別に用意する設計です。今回の PostgreSQL 構成は、同じデータ・同じスキーマのコピーをレプリカに配って読ませているので、モデルの分離まではしていません。古典的なプライマリ/レプリカ構成です。

一方で、書き込みの重い処理だけを Cosmos DB に逃がす部分は、用途ごとに保存先を使い分ける CQRS 的な発想に近いものです。

弱点は書き込み(MVCC)

PostgreSQL の MVCC は更新のたびに行全体をコピーするため、書き込み増幅と dead tuple による肥大化が起きやすい。読み取り中心のワークロードでは強くても、書き込みの急増には弱い、というのが公式ブログの正直な結論でした。唯一の大きな障害が書き込み急増だったのも、それを裏付けています。

なお公式ブログの最後では、今後の成長次第ではシャーディングされた PostgreSQL や分散システムの検討も続ける、とされています。「単一プライマリで永遠にいける」という話ではありません。

ISUCON目線で刺さったこと

ちょうど ISUCON の前日に読んだので、チューニングの観点でメモしておきます。

  • スケールさせる前に「プライマリ(DB)を守る」発想が先にあること
  • 接続プーリング、キャッシュ、重いクエリの排除、読み取り分離 — 手札はどれも地味で基本的なもの
  • 大手術(シャーディング)より、ボトルネックの切り分けとオフロードの積み重ね

派手な分散アーキテクチャではなく、「枯れた構成 × 規律ある運用」で限界まで引っ張る、という話でした。計測して、ボトルネックを特定して、そこだけ直す。当たり前のことを8億人規模でもやっている、というのが一番の収穫です。

参考

※ 本記事は公式ブログと報道をもとにした二次まとめです。正確な仕様や数字は公式ブログを確認してください。

最後に

いつの時代も基礎的な手法が1番強い…!!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?