mcpField
B
blob-store

blob-store

github.com/proyecto26クラウド・DevOps113309 回インストール1 日前に更新
リポジトリ

blob-store について

クラウドストレージ設計向けのスキルです。大容量の非構造化オブジェクトを対象に、ストレージ階層、耐久方式、アップロード方法、変更モデルを選びます。画像やバックアップ、データセットのアクセス制御とコストも扱います。

主な機能

  1. 01レプリケーションまたはイレイジャーコーディングの選択
  2. 02アクセス頻度に応じた階層選択
  3. 03単一またはマルチパートアップロード
  4. 04バージョニングとライフサイクルの設計
  5. 05アクセス制御と転送量の管理

活用シーン

  1. 01ユーザー投稿の画像や動画の保存
  2. 02バックアップやコンプライアンス用アーカイブの保管
  3. 03MLデータセットや大容量ファイルの管理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/proyecto26/system-design-skills --skill blob-store

インストール後、Claude Code で/blob-storeを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
deep-dive.md
references/providers/
aws.md
azure.md
gcp.md
generic.md

詳細

Blob ストア

画像、動画、バックアップ、モデルの重み、ドキュメントの Blob など、大容量で不変の非構造化オブジェクトを、文字列をキーとするフラットな名前空間に保存します。耐久性を高めるためにレプリケーションし、直接ダウンロードで提供します。設計を誤ると、数メガバイトの Blob を行指向データベースに詰め込むことになります(ワーキングセットが肥大化し、キャッシュ局所性が損なわれ、スループットが頭打ちになります)。あるいは、最初のディスク障害でデータを失うファイルサーバーを独自に作ることになります。

どのような場合に使うか

オブジェクトが大きく(KB〜GB)、一度書き込んだ後に何度も読み取られ、キーを指定して常にオブジェクト全体を取得し、オブジェクトの内部をクエリすることがない場合です。写真・動画ストア、ユーザーアップロード、バックアップ、データレイク/ML データセット、静的サイトのアセット、ログアーカイブなどが該当します。アクセスパターンは PUT key → GET key で、耐久性が重要であり、総データ量が大きすぎるか、アクセス頻度が低すぎてプライマリデータベースに置けない場合に適しています。

使わない場合

クエリ、フィルタリング、並べ替え、結合を行う小さな構造化レコードには使いません。それには data-storage が適しています。トランザクション、セカンダリインデックス、部分更新が必要なデータにも使いません(Blob はその場で編集するのではなく、全体を置き換えます)。小さな値の低レイテンシ読み取りには、KV キャッシュや caching の方が適しています。1 台のマシン上に、今後増えることのないファイルが少しあるだけなら、ローカルファイルシステムで十分です。Blob ストアは、まだ必要のない運用負荷です(YAGNI)。実際にはデータベースであるワークロードを「オブジェクトストレージ」と呼ぶことは、失敗パターンその2です。

まず確認すること

  • オブジェクトサイズの分布 — 平均サイズと p99 サイズはどのくらいですか?(チャンク化、マルチパートのしきい値、読み取りをストリーミングするかバッファリングするかが決まります。)→ back-of-the-envelope。
  • 読み取りと書き込みの比率、およびアクセスの新しさ — 一度書き込んで何度も読み取りますか?データはどのくらいの速さでコールドになりますか?(ストレージ階層化と CDN の前段配置に影響します。)
  • 耐久性と可用性の目標 — 耐久性は何ナインが必要ですか?読み取りが一時的に失敗してもよいですか、それとも常に成功する必要がありますか?(レプリケーションかイレージャーコーディングか、マルチリージョンかが決まります。)
  • アクセス制御 — パブリック、プライベート、またはオブジェクトごとの期限付きアクセス許可のどれですか?(署名付き URL。)
  • 可変性と履歴 — オブジェクトは変更されますか?以前のバージョンを保持する必要がありますか(コンプライアンス、取り消しなど)?(バージョニング+ライフサイクル。)
  • エグレスの状況 — 誰が、どこから、どのくらいの頻度で読み取りますか?(CDN による負荷軽減、エグレスコスト。)

選択肢

耐久性の方式(コピー数とその構成)

  • N ウェイレプリケーション — N 個の完全なコピーを、異なるノード/ラック/AZ に保存します。オブジェクトが小さく、アクセス頻度が高く、レイテンシが重要な場合に使います。最も単純で理解しやすい方式です。
  • イレージャーコーディング(EC) — オブジェクトを k 個のデータシャードと m 個のパリティシャードに分割します。任意の k 個から復元できます。大規模なコールドデータに使います。レプリケーションの 3 倍ではなく、約 1.4 倍のオーバーヘッドで同等の耐久性を実現できます。(仕組みについては references/deep-dive.md を参照してください。)

ストレージ階層(価格、レイテンシ、取得のトレードオフ)

  • ホット/スタンダード — ミリ秒単位で読み取れますが、GB あたりの料金は最も高くなります。頻繁に提供するオブジェクトに使います。
  • クール/低頻度アクセス — ストレージ料金は安くなりますが、取得料金がかかり、レイテンシもやや高くなります。バックアップや月に数回読み取るデータに使います。
  • アーカイブ/コールド — ストレージ料金は最も安く、取得に数分〜数時間かかります。コンプライアンス目的の保持や、ほとんどアクセスされないデータに使います。リクエストパス上の処理には決して使いません。

アップロード方法

  • 単一 PUT — 1 回のリクエストでアップロードします。小さなオブジェクト(マルチパートのしきい値未満)に使います。
  • マルチパート/再開可能 — パートに分割し、並列でアップロードして、パートごとに再試行し、完了時に確定します。大きなオブジェクトや不安定なネットワークに使います。しきい値を超える場合の標準的な方式です。

変更モデル

  • 不変+バージョニング — 書き込みのたびに新しいバージョンを作成し、削除はトゥームストーンとして記録します。履歴、取り消し、誤上書きの防止が重要な場合に使います。
  • その場で上書き(最終書き込み優先) — 最も単純で、履歴は残りません。最新のオブジェクトだけが必要で、古いコピーの保存が無駄になる場合に使います。

トレードオフ

選択肢解決できること悪化すること切り替えるタイミング
N-way レプリケーションシンプルで、読み取りと再構築が高速ストレージコストが3倍以上データが大容量または低頻度アクセスで、コストが最優先になる場合 → イレイジャーコーディング
イレイジャーコーディングストレージ使用量約1.4倍で同等の耐久性を実現フェッチごとにCPU負荷が高まり、複数ノードからの読み取りが必要。小さなオブジェクトの読み取りが遅く、再構築コストも高いオブジェクトが小さく頻繁にアクセスされ、レイテンシが重要な場合 → レプリケーション
ホットティア低レイテンシでの提供GB あたりのコストが最も高いデータへのアクセス頻度が下がり、ほとんど読み取られなくなった場合 → クール/アーカイブ
アーカイブティア保存時のコストが最も安い最初のバイトを取得するまで数分〜数時間かかり、取得料金も発生レイテンシの影響を受ける経路で使われるようになった場合 → ホット/クール
マルチパート/再開可能なアップロード大容量ファイルでも不安定な接続に耐え、並列転送が可能クライアント側のロジックが増え、孤立したパートにもコストがかかるオブジェクトが小さい場合 → 単一の PUT
バージョニング取り消し、履歴、上書き保護ストレージ使用量が気づかないうちに増加し、ライフサイクルによる期限切れ処理が必要最新のものだけが必要な場合 → 上書き、最終書き込み優先
署名付き URLアプリから転送処理を切り離し、アクセス範囲を限定URL の漏えいや過剰な権限付与、クロックスキューによる有効期限切れの不具合コンテンツが完全に公開されている場合 → CDN +公開読み取り

負荷が高い状況での動作

ブロブストアはデータベースのように「停止」することはあまりありませんが、特定の形で問題を増幅させます。

  • ホットオブジェクト/ホットプレフィックス: 拡散したファイルや、多数の書き込みで同じプレフィックスを共有するキー方式によって、負荷が1つのパーティションに集中します。対策: ホットな読み取りを CDN(content-delivery)の背後に置き、キーのプレフィックスをランダム化またはハッシュ化し、ホットオブジェクトを複製します。
  • メタデータインデックスのボトルネック: キーからシャードの場所への対応を管理するインデックスが、実際の単一障害点(SPOF)であり、スループットの上限になります(小さなオブジェクトが数百万個あるほうが、巨大なオブジェクトが数個ある場合よりもはるかに大きな負荷になります)。対策: インデックスをシャーディングし、頻繁に参照される検索結果をキャッシュし、オブジェクトの数を減らしてサイズを大きくします。
  • コールドティアへの昇格時のサンダリングハード: アーカイブデータへの読み取りが集中すると、時間がかかりコストも高い一括取得が発生します。対策: 取得処理を非同期として公開し、キューに入れ(messaging-streaming)、レイテンシについて事前に伝えます。
  • 孤立したマルチパートアップロード: 中断されたアップロードによってパートが残り、気づかないうちにコストが発生します。対策: 不完全なアップロードを N 日後に中止するライフサイクルルールを設定します。
  • エグレスの急増/コストの膨張: 人気のあるオブジェクトをオリジンから直接配信すると、帯域幅が飽和し、エグレス料金が膨らみます。対策: 手前に CDN を配置します。オリジンが配信するのはキャッシュの補充であり、エンドユーザー向けではありません。
  • 書き込み中の部分障害: 書き込みの途中でノードが停止します。対策: 耐久性クォーラム(レプリカまたは EC シャード)が満たされるまで書き込みを確認応答せず、バックグラウンド修復で耐久性が不足したオブジェクトを再レプリケーションします。

監視項目: 操作ごとのリクエスト率とエラー率(PUT/GET/DELETE)、最初のバイトまでの p99 レイテンシ、耐久性修復キューの深さ、プレフィックスごとの負荷、未完了のマルチパート数、エグレス量とコスト。

適用方法

  1. 入力条件を明確にする — オブジェクトサイズの分布、読み取りと書き込みの比率、耐久性の目標、アクセス制御、エグレスの特性を確認します(最初に確認することを参照)。クエリ対象がごく小さな構造化レコードであれば、そこで検討を止めて data-storage を使います。
  2. トレードオフ表から選ぶ — 耐久性の方式(小規模・高頻度アクセスにはレプリケーション、大規模・低頻度アクセスにはイレイジャーコーディング)、デフォルトのストレージ階層、サイズに応じたアップロード方法、履歴の要否に応じた変更モデルを選びます。
  3. 主要な設定を決める — ホットスポットを避けるキー/プレフィックスの方式を設計し、マルチパートアップロードのしきい値とパートサイズを設定し、ライフサイクルルール(階層の移行、バージョンの有効期限、未完了アップロードの中止)を定義して、署名付きURLの有効期間を決めます。
  4. 負荷をかけて選択を検証する — 高負荷時の動作にある各項目(ホットオブジェクト、メタデータのボトルネック、低頻度データの取得集中、孤立したパート、エグレスの急増)を確認し、このトラフィックで発生し得る問題に対する軽減策があることを確かめます。
  5. 数値で容量を見積もる — レプリケーション/ECのオーバーヘッドを含む総ストレージ容量、オブジェクト数(メタデータインデックスの負荷)、ピーク時のPUT/GET QPS、月間エグレスを算出します。→ 重要な数値を参照します。
  6. プロバイダーを選ぶ — まず汎用レシピを使い、ユーザーがクラウドを指定した場合にのみプロバイダーのファイルを開きます(プロバイダーの選択を参照)。
  7. 回答でトレードオフを示す — ここで行った各選択について、Decision | Solves | Worsens | Change it when… の表に1行ずつ記載します(例:選択肢、そのストア、障害時のポリシー)。最後の列には具体的な変更のきっかけ(数値または観測可能なシグナル)を記載します。そのうえで、最初に問題が発生する箇所を示します。

すべきこと、してはいけないこと

すべきこと

  • Blobはストアに保存し、データベースにはポインター(キー+メタデータ)を保存します。行にバイト列を保存してはいけません。
  • オブジェクトは不変として扱います。履歴が必要な場合は、その場で編集せずバージョンを作成します。
  • 公開読み取りや高頻度アクセスの読み取りはCDN経由にし、オリジンはエンドユーザーではなくキャッシュへのデータ供給を担うようにします。
  • しきい値を超えるサイズのアップロードにはマルチパート/再開可能なアップロードを使い、ライフサイクルルールで未完了アップロードを中止します。
  • キーのプレフィックスを設計して負荷を分散します。カーディナリティの高いプレフィックスはハッシュ化するか、シャッフルします。
  • ライフサイクルルールを設定して、低頻度アクセスのデータを下位階層に移し、古いバージョンを自動的に期限切れにします。

してはいけないこと

  • 大きなBlobをリレーショナル/NoSQLの行に保存してはいけません。ワーキングセットとスループットが損なわれます。
  • アーカイブ階層を読み取りパスに使ってはいけません。取得に数分から数時間かかるため、リクエストがタイムアウトします。
  • 人気のあるオブジェクトをCDNなしでオリジンから直接配信してはいけません(エグレスが急増します)。
  • 広範な権限を持つ署名付きURLや、有効期間が長い署名付きURLを配布してはいけません。対象を絞り、有効期間を短くします。
  • イレイジャーコーディングは無料ではありません。CPU負荷、複数ノードからの読み取り、高コストな再構築が発生します。
  • 数百万件の小さなオブジェクトを軽視してはいけません。上限を決めるのはディスクではなく、メタデータインデックスです。

重要な数値

設計を左右する数値は、耐久性のオーバーヘッドを掛けた総保存バイト数(レプリケーションは約3倍、イレイジャーコーディングは約1.3~1.5倍)、オブジェクトの数(メタデータインデックスの拡張性はサイズではなく件数に左右されます)、ピーク時のアップロード/ダウンロードQPS、月間エグレス(多くの場合、最大のコスト要因)です。オブジェクトストレージの耐久性目標は一般にイレブンナイン程度とされていますが、これは所与の値ではなく、耐久性の方式によって定める設計目標として扱います。ストレージ容量、帯域幅、QPSの実際の計算と単位換算には back-of-the-envelope を使い、ここの表を再掲しないでください。

インターフェースの概要

契約はシンプルで、キーでアドレス指定します。

PUT    /{bucket}/{key}        body=bytes, headers: Content-Type, optional checksum
GET    /{bucket}/{key}        → bytes (supports Range for partial/streamed reads)
DELETE /{bucket}/{key}        → tombstone (new version if versioning on)
HEAD   /{bucket}/{key}        → metadata only (size, etag, version-id)
# multipart: Initiate → UploadPart×N (parallel, retryable) → Complete | Abort
# signed URL: presign(GET|PUT, key, expiry) → time-limited URL the client uses directly

キーがインデックス全体です(例:userId/2026/photo-uuid.jpg)。アクセスパターンとプレフィックスの分散の両方を考慮して選びます。etag/チェックサムにより、クライアントは整合性を検証し、条件付きリクエストを実行できます。データベースにはこのキーとアプリケーションのメタデータを保存し、バイト列は保存しません。

プロバイダーの選択

まず上記の汎用レシピを使います。ユーザーがクラウドを指定した場合は、マネージドサービスへの対応付け、クォータ/制限、プロバイダー固有のトレードオフを確認するために references/providers/<provider>.md を読みます。そのプロバイダーのファイルが存在しない場合は、汎用レシピを回答として使います。

図

アップロード/ダウンロードの経路(クライアント → 署名付き URL → ストア、GET を前段で処理する CDN、キー → シャードのインデックスマッピング)または EC の書き込みファンアウトを可視化するには、プラグイン内の architecture-diagram スキルを使用してください。メタデータインデックスを独立したノードとして、CDN をエッジレイヤーとして示してください。ここに Mermaid を埋め込まないでください。

関連する構成要素

  • content-delivery — これと組み合わせます。CDN が Blob オリジンの前段に配置され、繰り返しの読み取りはエッジから配信され、ストアはキャッシュへの格納時のみ処理します(エッジキャッシュはそちらが担当します)。
  • data-storage — 大規模な非構造化オブジェクトに対する代替手段です。Blob はここに保存し、ポインター(キー + メタデータ)を DB に保持します。メタデータのシャーディング/インデックス作成はそちらが担当します。
  • back-of-the-envelope — ストレージ、オブジェクト数、QPS、エグレスのサイジングで依存します(レプリケーションと EC の選択、およびティアの選択に使う数値はそちらにあります)。
  • messaging-streaming — コールドティアからの取得やアップロード後の処理(トランスコード、サムネイル生成)などの非同期作業をキューに入れるために組み合わせます(配信保証はそちらが担当します)。
  • caching — ホットな小さなオブジェクトの読み取りとメタデータ検索の負荷軽減に組み合わせます。
  • system-design — オーケストレーターに属する概念です。推論ループ、トレードオフの検討方法、10 の障害モードを扱います。

参考資料

  • references/deep-dive.md — チャンク分割、メタデータインデックス、イレイジャーコーディングの計算と読み取り経路、耐久性/修復、バージョニング + ライフサイクル、マルチパートの内部処理、署名付き URL の仕組みを説明します。ストアを詳細に設計する際に読んでください。
  • references/providers/{generic,aws,azure,gcp}.md — 各環境のサービス対応表、判断を左右する制限事項、落とし穴を説明します。

コメント