世界を動かす技術を、日本語で。

AWS S3が遅いHDDの上で1ペタバイト毎秒をどのように提供するか

概要

AWS S3は、膨大なスケールで動作する分散型ストレージサービス。 HDDの物理的制約を克服し、並列化とイレイジャーコーディングで高い可用性・耐久性・スループットを実現。 データ分散とロードバランシングの工夫により、ホットスポット回避と予測可能なパフォーマンスを維持。 マルチパートアップロードやバイトレンジGETなどのAPI設計で効率的なアクセスを可能に。 巨大システムゆえに、規模が大きくなるほど全体の負荷が平準化され、予測性が向上。

AWS S3の驚異的なスケール

  • AWS S3 は、API経由でオブジェクトを保存・取得できる スケーラブルなマルチテナントストレージサービス
  • 可用性耐久性 が極めて高く、コストも比較的低廉
  • 400兆以上のオブジェクト毎秒1.5億リクエストピーク時1PB/s超のトラフィック数千万台のHDD を運用
  • スケールを支える中核は意外にも HDD(ハードディスクドライブ)
  • HDDはIOPS・レイテンシーに制約があるが、「 安価な大容量」という強みを最大活用

HDDの物理的制約と進化

  • HDD は物理的な動作(回転・アーム移動)が必要なため ランダムアクセスが遅い
  • 30年以上 IOPSは約120で頭打ち、レイテンシーも大きな進歩なし
  • 価格は60億倍安価容量7,200,000倍増加サイズ・重量も大幅減少
  • シーケンシャルアクセス に最適化されており、 ログ構造 のデータストアと相性が良い

S3のストレージバックエンドとLSM

  • S3の ShardStoreLSM(Log-Structured Merge Tree) ベース
  • 書き込みはシーケンシャル なのでHDDの性能を最大限活用
  • 読み込みはランダムアクセス が多く、HDDの弱点となる
  • 平均的なランダムリードは0.5MBで約11ms、45MB/s程度が限界

並列化によるスループット向上

  • S3は大規模な並列化 でHDDの制約を克服
  • 1TBファイルを1台のHDDに保存すると 最大300MB/s だが、 20,000台に分散 すれば TB/s級の並列リード が可能
  • これを実現するのが イレイジャーコーディング(EC)

イレイジャーコーディングの仕組み

  • K個のデータシャードM個のパリティシャード でデータを分割・冗長化
  • S3では 5-of-9スキーム (5データ+4パリティ)を採用
  • 最大4シャード喪失まで耐性1.8倍の容量オーバーヘッド で済む
  • 並列リード先が9箇所 になり、ホットスポット・ボトルネックを緩和
  • シャードが小さいため ヘッジリクエスト も低コストで実施可能

エンドツーエンドの並列化とAPI設計

  • ユーザー側 :ファイルをチャンク分割してアップロード/ダウンロード
  • クライアント側 :複数のフロントエンドサーバーへリクエスト送信
  • サーバー側 :オブジェクトを複数ストレージサーバーに分散
    • マルチパートアップロード で複数スレッドによる高速PUT
    • バイトレンジGET で部分的な高速リード
  • 大量の小さなリクエストを並列化 することで全体スループットを最大化

ロードバランシングとホットスポット回避

  • データ配置はランダム化 が基本
  • Power of Two Random Choices で、2つのランダムノードから負荷の少ない方を選択
  • 新しいデータほどアクセス頻度が高い ため、時間とともに自然に「冷却」される
  • リバランス も頻繁に実施し、空き容量やI/Oを有効活用
  • 新規ラック追加時も 自動的にデータを分散

巨大システムならではの予測性

  • 規模が大きいほど全体負荷が平準化 し、ピークと平均の差が縮小
  • 多数の独立したワークロードが同時にバーストしないため、 総合的な負荷が予測しやすい
  • マルチテナント による経済性とスムーズなオペレーション

まとめ:S3のエンジニアリングの要点

  • エンドツーエンドの大規模並列化 でHDDの物理的制約を克服
  • イレイジャーコーディング による効率的な冗長化と高スループット
  • ランダム配置・リバランス・ホットスポット回避 の工夫
  • API設計 で並列化・部分リード・マルチパートアップロードを推奨
  • 巨大システムの規模の経済性 を最大限に活用

S3は、もともとバックアップや静的ファイル用のサービスとして始まったが、今や世界最大級の 汎用ストレージ基盤 へと成長。 その裏には、HDDの制約を逆手に取った 分散システム設計運用ノウハウ が詰まっている。

Hackerたちの意見

S3についてもっと面白い記事があると思うんだけど、「Building and operating a pretty big storage system called S3」ってやつ。

すごくいい記事だった、ありがとう!

当時話題になったこと: S3というかなり大きなストレージシステムの構築と運用 - https://news.ycombinator.com/item?id=36894932 - 2023年7月(コメント160件)

HDDを考慮して設計されたオープンソースのサービスで、似たようなパフォーマンスを出せるものってある?大手のはHDDとあんまり相性良くないって知ってるけど、MinIO、Swift、Ceph+RadosGW、SeaweedFSとか、みんなフラッシュ専用の展開を勧めてるよね。最近Garageに興味を持ってるんだけど、デザインがかなり違うみたい(ECなし)。

Ceph以外にも軽くググってみたら、Glusterっていうのもあるね。「一般的なオフ・ザ・シェルフのハードウェアを使って、大規模な分散ストレージソリューションをメディアストリーミングやデータ分析、その他のデータや帯域幅を多く使うタスクのために作れる」って自称してる。オープンソースで無料だし。ただ、直接の経験はないけどね。

どれも同じように機能するけど、たくさんのデータセンター分のドライブが必要で、そういう展開はほんと少ないよね。横のスケーリングと縦のスケーリングのトレードオフがあるから、フラッシュの方が速いアクセスにはスペースやコスト効率がいいんだよね。

LustreとZFSも似たような速度が出せるよ。ただ、高いIOPSが必要なら、LustreにはMDSにフラッシュが必要だし、ZFSには専用の書き込み用と読み込み用のLog SSDが必要だね。

SeaweedFSはここ数年でかなり進化して、RDMAサポートやECも追加されたよ。

前の仕事ではSwiftStackを使ったオブジェクトストレージがあったんだけど、メタデータの保存にはSSDを使って、オブジェクトは普通のHDDに保存してた。まあ、そこそこうまくいってたよ。

Ceph+RadosGWはHDDと相性がいいと思うよ。条件としては、1) インデックスプールにはSSDを使うこと、2) HDDプールから得られるIOPSの数を現実的に考えることが大事。あと、個々のクライアントのIOPSに対しては、トリプルストレージやエラーチェックを使ってもIOPSが掛け算になることを忘れないで。S3もIOPSの掛け算があって、たくさんのHDDで解決してる。大きなオブジェクトストレージで、主に4MBのチャンクをストリーミングする場合は、特に問題ないけど、小さなランダムな読み書きがたくさんある場合や、一つの大きなキーに対しては、バックストアがついてこれるか確認する必要があるね。

Apache Ozoneは、100ペタバイト以上のクラスターをいくつも運用してるよ。容量はHDDに、メタデータはSSDに載せてる。更新されたドキュメント(新しいドキュメントの準備中): https://kerneltime.github.io/ozone-site/

11年間、プロダクションのCephクラスターを運用してきて、これまでのところ大規模なアップグレードのためのフルスケジュールダウンタイムは1回だけだったよ。3世代のハードウェアを使ってね。簡単とは言わないけど、難しいとも言えないかな。以前はradosgwのインデックス用にSSDを使ったり、いくつかのVM用に速いプールを作ったり、バルクオブジェクトストレージにはハードドライブを使ってたんだ。5ノードでそれぞれ10台のドライブを運用してたから、重いリカバリーの時にたまにIOPの問題があって疲れたから、最後のアップグレードで100% NVMeドライブに移行したんだ。コストを抑えるために、良い取引が出たときにeBayで中古のエンタープライズ用マイクロンのドライブを買ってたよ。それ以来、何を投げてもパフォーマンスの問題は出てない。お勧めするけど、他のオプションについての経験はないからね。理論的にはまだ一番の選択肢だと思う。ただし、CephFSには近づかない方がいいよ。パフォーマンスが本当にひどくて、プロダクションで使うには自分を足元から撃つことになるから。

S3ってSSDで動いてるの?正直、スタンダードティアはSSDで、遅いティアはHDDかそれより遅いシステムを使ってるんだと思ってた。

本当に遅いティアはテープだと思ってたんだけど。

S3はSSDで動いてる部分あるの? S3のKeyMapインデックスはSSDを使ってるよ。今の時点で、SSDがホットオブジェクトのキャッシングや新しいゾーン製品の読み取りパスに使われてるとしても驚かないな。

新しいS3 Express One ZoneはSSDでサポートされてると考えられてるけど、アマゾンがそれを明言してるわけじゃないと思う。

ストレージ自体は多分(ほとんど)HDDにあると思うけど、メタデータやインデックスなんかはもっと速いフラッシュストレージに保存されてるんじゃないかな。少なくとも、小規模なCephクラスターのMDSサーバーにはそれが一般的なアドバイスだし。S3はそれよりも数桁大きいけどね…

上で言ったコメントを繰り返すけど、スタンダードティアではリクエストが高額だから、ディスクのスペースを無駄にするのがコスト的に効果的なんだ。IOPS/TB比がドライブが提供できるものより高い場合ね。でも、それ以上に高くはないよ。最新世代のドライブは約30TBを保存できるけど、AWSがそれにいくら払ってるかは分からないけど、適当な予想だと300ドルから500ドルくらいかな。それは30TBのSSDよりずっと安いよ。あと重要なのは、そういうディスクを高密度システム(例えば、4Uに100台のドライブ)に入れられるから、AWSならトータルコストに対して25%くらいしか追加されないけど、他の人たちにはもう少し高くなるかもね。たくさんのSSDを収納するボックスのスロットあたりのコストはかなり高いみたい。

S3の技術スタックって誰か知ってる?モノリスなのか、それとも複数のサービスなのか?キューやキャッシュ、長時間動いてるワーカーがたくさんあるんじゃないかなって思ってる。

コンウェイの法則と、それがS3のアーキテクチャ(300以上のマイクロサービスから成る)にどう影響しているか

アマゾンは、モノリスとマイクロサービスの中間に位置するシステム指向アーキテクチャのアプローチを好んでいるよ。小さなサービスをたくさん使うのではなく、大きなサービスで多くの作業を処理する方向にバイアスがかかってるから、リクエストの準備、送信、受信、処理のコストやレイテンシをできるだけ避けられるようにしてるんだ。10年近く前にいた頃からS3は変わってると思うから、今の情報ではないけど、その頃はだいたい12個くらいの主要なサービスがあった。オブジェクトを置くリクエストは、ディスクに行くまでに数個のサービスにしか触れなかったし、取り出しも同じような感じだった。データの整合性や耐久性の操作を扱うサービスがいくつかあって、ストレージサーバー自体のソフトウェア、そしてオブジェクトとストレージのマッピングを維持するものもあった。

10年前にS3のインデックスチームでSDEをやってたけど、コアスタックはあまり変わってないと思う。S3は主にJavaベースのウェブサービスのレイヤーで構成されてる。ホットパス(オブジェクトの取得/配置/リスト)は、すべて同期APIサーバーで処理されていて、キューやワーカーは使ってない。標準的なJavaウェブサービススタックが1秒間にどれだけのトランザクションを処理できるかの最高の例だと思う。取得のリクエストでは、まずロードバランサーの背後にあるフロントエンドのHTTP APIサーバーの群にアクセスする。パーティショニングはキー名のプレフィックスに基づいてるけど、最近それをデカップリングする作業をしたって聞いた。リクエストはインデックスの群に送られて、キー名と内部ストレージIDのマッピングを見つける。これがフロントエンドに返されて、ストレージレイヤーにIDを使って実際のデータを取得するように呼び出される。これは、大規模なスケールで同期APIレスポンスを提供するための非常にシンプルなマルチレイヤー分散システムデザインだよ。唯一の新しい点は、バックエンドの通信が自家製の簡素化されたHTTPバリアントを使っていることで、確かSTUMPYって呼ばれてた。HTTPを使わなかったのは愚かなアイデアだったけど、そのサービスは古くて、元々は主力エンジニアが自分のフレームワークやプロトコルを自由に作れた時代に作られたから、今はそれに縛られてる。私がいた頃からSTUMPYをHTTPに置き換える大規模な作業をしたかもしれないね。

マイクロサービスがたくさん。5年前にライフサイクルに取り組んでたけど、StandardからGlacierへの移行パスには7つ以上のマイクロサービスが関わってた。400兆のキーの中からライフサイクルアクションの対象となるものを特定するだけでも、各オブジェクトのメタデータをバケットのライフサイクルポリシーと比較する大規模なビッグデータの仕事だった。あるバケットが1PB以上のデータを同じ日に移行または削除するためのライフサイクルルールを追加したときは、いつも楽しいオンコールだった。うちのキューイングはこれらのキューをうまく処理できるようになってたけど、アラートは大きなジョブを持つ単一の顧客のバックログと、システム全体が迅速に処理できていないことを区別する方法を見つけられなかった。確か、私が辞めるときにはこれが修正されてたはず。

昨年のre:InventでのS3の内部についての良いトークがあるよ: https://www.youtube.com/watch?v=NXehLy7IiPM

彼らが書いた唯一の学術論文はこれだよ: https://www.amazon.science/publications/using-lightweight-fo... (まあ、他にも一、二本提出したかもしれないけど、これが唯一出版されたやつだね)

この記事は楽しめたけど、見出しの答えは明らかだと思う:並列処理だね。

それは「月に行く方法は明らかだ:旅行することだ」と言ってるようなもんだね。

あんまりそのスケールでストレージのI/O速度について考えないな(ほんと、誰が考えるんだ?)。昔、RAID0を使ってHDDにデータを早く保存してたことがあったけど、それはかなり前の話。面白いキャッシングシステムがあると思ってたし、ホットとコールドのオブジェクト用にストレージの階層があるんだろうなって。記事を読んでみたら、並列処理が素晴らしい選択肢だってのは明らかだったけど、S3の詳細なスキームやエラー訂正については全然考えてなかった。並列処理が一言で言うとまとめられるけど、詳細があったからこそ記事を読む価値があったと思う。minioも似たようなスケーリングの話があるだろうね:並列処理。

記事のタイトルの質問はちょっと誤解を招くと思う。S3全体のピークスループットに焦点を当ててるから。興味深い質問は「GETのスループットがHDDのスループットを超えるのはどういうことか?」だと思う。もし単にレプリケートするだけなら、異なるHDDをターゲットにした多くの読み取りを行うことで、S3全体のスループットを大きくすることはできる。でも、最大HDDスループット * GETの数に制限されるよ。S3はそんなに制限されてないから、そこが面白くて明白じゃないところだね!

数千万のディスクがあると仮定すると、エンタープライズHDDは数十TBの範囲にあるので、AWSのS3ストレージ容量はおそらく数百エクサバイトの規模になると思う。これは地球上で最大のストレージシステムかもしれないね。

生産規模のエンタープライズHDDは30TBの範囲で、50TBも近づいてきてるね…

ユタ州のあるデータセンターは、2013年以降にハードウェアをアップグレードしていれば、それを上回るかもしれないね。 https://www.forbes.com/sites/kashmirhill/2013/07/24/blueprin...

これに似たものをホームラボで再現できるかな?

ガレージ

ここにはいくつかの事実誤認があるけど、全体の流れには影響しないよ。例えば、S3が5:9のシャーディングスキームを使っているという主張。実際には、いろんなシャーディングスキームを使っていて、確か5:9はその中にないはず。主な理由は、物理バイト1.8に対して論理バイト1の比率がHDDコストにとってひどいから。これをかなり下げられるし、より広い並列処理と良い可用性の保証も得られるよ(考えてみて:もし全AZがダウンしたら、オブジェクトがGETできなくなるまでにどれだけのシャードを失うことができるか?)。

フルプラッタのシーク時間: 約8ms; ハーフプラッタのシーク時間(平均): 約4ms。二点間の平均距離(最初は現在地、二つ目はターゲット地点)が[0 .. +1]の区間で均等に分布している場合、0.5ではなく1/3になる。フルプラッタのシーク時間が8msなら、平均シーク時間は2.666msになるはず。

読み取りヘッドをトラック間で移動させるために加速があるから、4msになることもあるよ。短い距離だと、読み取りヘッドのピーク速度が低くなるのと、動作の終わりでの定常的な要因が影響してくるからね。

現代のドライブでのフルシークは8msよりも25msに近いね。もし自分のマシンにハードドライブがあって、ルートアクセスがあれば、自分でテストするのは簡単だよ。--readonlyオプションを使ってfioを起動して、ディスクの先頭と末尾でブロックを交互に読み取る手作りのトレースを与えればいいんだ。(--readonlyはドライブに書き込む可能性のあるコードを完全に無効にするよ) 最近のドライブに関する1/3の数字が正確じゃない理由を説明している良い論文があるよ - https://www.msstconference.org/MSST-history/2024/Papers/msst... ドライブのメカニクスやパフォーマンスについて他に質問があれば、喜んで答えるよ。

S3が基本サービスにハードドライブを使ってることは、価格を見て、月あたりのGBあたりのコストを倍にするIOPSレートを計算することで推測できるよ。S3のGETやPUTリクエストは十分に高額だから、AWSは高性能なテナントを満たすためにディスクスペースを無駄にしても大丈夫なんだ。でも、それ以上に高くはないよ。