コンテンツにスキップ

第35章: 分散ストレージ階層(KV / D1 / R2 / Durable Objects)

伝統的なコンピュータアーキテクチャでは、CPUの近くにレジスタや高速なSRAM(L1/L2/L3キャッシュ)があり、その下にDRAM(メインメモリ)、さらに低速かつ大容量なSSD/HDDや外部ネットワークストレージが存在します。

Cloudflare OS においても、地球全体を単一のコンピュータと見立てた「グローバル・メモリ階層(Global Storage Hierarchy)」が設計されています。

エッジでミリ秒未満のレイテンシを実現しつつ、一貫性とデータ永続性をいかに担保するか。本章では、ストレージ製品群をコンピュータのハードウェア階層にマッピングし、CAP定理のトレードオフと実践的なデータ配置戦略を解説します。


1. Cloudflare OSのストレージ階層モデル

ハードウェア相当Cloudflare サービス特性レイテンシ一貫性モデル (CAP)推奨ユースケース
CPU L1/L2 キャッシュWorkers Cache API / KV超高速・エッジ直近< 10msAP(結果的一貫性)セッション検証、静的設定、フラグ
RAM (メインメモリ)Durable Objects (In-Memory)単一インスタンス・強整合性10ms - 50msCP(強い一貫性)共同編集、在庫引当、レートリミット
ローカル NVMe SSDCloudflare D1 (SQLite)リレーショナル・分散リード20ms - 100ms読み取り: AP / 書き込み: CPユーザーマスタ、注文履歴、CMS
外部 HDD / Cold StorageCloudflare R2 (S3互換)大容量・低コスト・イグレス無料50ms - 200ms強整合性 (オブジェクト単位)画像・動画、ログアーカイブ、バックアップ

2. 各レイヤーのアーキテクチャ詳細

2.1 Cache API & KV(エッジキャッシュ階層)

  • 仕組み: 全世界330都市以上のデータセンターに配置されたKey-Valueストア。Cache APIはデータセンターローカルに留まり、KVはバックグラウンドで全世界のPoPへ非同期レプリケーションされます。
  • トレードオフ: 書き込みが全拠点へ伝播するまでに最大60秒の遅延(Eventual Consistency)が発生します。「今すぐ全拠点で最新値が読めなくても致命的ではないが、10ms未満で高速に応答したい」データに最適です。

2.2 Durable Objects(グローバルRAM階層)

  • 仕組み: 地球上の「特定の1箇所」にのみ存在するステートフルなActorインスタンス。メモリ上にJavaScriptオブジェクトを常駐させ、ミリ秒未満のIn-Memory操作と、同一トランザクション内でのローカルストレージ(SQLiteバックエンド)への永続化を行います。
  • トレードオフ: 全世界からのアクセスがそのDOが存在する特定リージョンへルーティングされるため、遠隔地からのアクセスにはネットワークRTT(往復時間)が生じます。しかし、競合状態(Race Condition)を完全に排除できるため、厳密なトランザクションが要求される領域で不可欠です。

2.3 Cloudflare D1(エッジRDBMS階層)

  • 仕組み: サーバーレスSQLiteをベースとし、プライマリデータベース(書き込み担当)と、世界各拠点に自動配置されるリードレプリカ(読み取り担当)で構成されます。
  • トレードオフ: SELECTクエリは最寄りのエッジで極めて高速に実行されますが、INSERT/UPDATE/DELETEなどの書き込みは単一のプライマリノードへ中継されます。

2.4 Cloudflare R2(ブロック/オブジェクトストレージ階層)

  • 仕組み: AWS S3互換の分散オブジェクトストレージ。最大の革新は データ転送料(Egress料金)が完全無料 である点です。
  • トレードオフ: ミリ秒単位の頻繁なランダムアクセスには不向きですが、Workersのエッジとゼロコピーで連携し、動画ストリーミングや大容量ファイル配信のハブとして機能します。

3. 実践:階層型キャッシュ・データアクセスパターンの実装

コンピュータのL1キャッシュミス時にRAMやディスクへフォールバックするのと同様のパターンをWorkersで構築します。

src/storage-hierarchy.ts
import { Hono } from 'hono';
type Bindings = {
KV_CACHE: KVNamespace;
DB: D1Database;
STORAGE: R2Bucket;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get('/user/:id', async (c) => {
const userId = c.req.param('id');
const cacheKey = `user:cache:${userId}`;
// 1. [L1 Cache] KVから超高速取得を試みる (レイテンシ ~10ms)
const cached = await c.env.KV_CACHE.get(cacheKey, 'json');
if (cached) {
return c.json({ data: cached, source: 'L1_CACHE (KV)' });
}
// 2. [SSD / DB] キャッシュミスのためD1から取得 (レイテンシ ~50ms)
const user = await c.env.DB.prepare(
'SELECT id, name, email, avatar_key, updated_at FROM users WHERE id = ?'
).bind(userId).first();
if (!user) {
return c.json({ error: 'User not found' }, 404);
}
// 3. 次回アクセスのためにL1キャッシュに非同期書き込み (TTL: 60秒)
c.executionCtx.waitUntil(
c.env.KV_CACHE.put(cacheKey, JSON.stringify(user), { expirationTtl: 60 })
);
return c.json({ data: user, source: 'PRIMARY_STORAGE (D1)' });
});
export default app;

4. CAP定理とストレージ選定の判断フローチャート

flowchart TD
    Start[データ設計の開始] --> Q1{厳密な書き込み一貫性や<br/>複数ノード間の排他制御が必要か?}
    
    Q1 -- Yes --> Q2{リレーショナルなクエリ<br/>SQLが必要か?}
    Q2 -- Yes --> D1[Cloudflare D1<br/>プライマリ書き込み + レプリカ読み取り]
    Q2 -- No --> DO[Durable Objects<br/>単一整合性 + In-Memoryステート]
    
    Q1 -- No --> Q3{データ形式は?}
    Q3 -- 構造化/JSON/Key-Value --> Q4{超低レイテンシ読み取りが最優先か?}
    Q4 -- Yes --> KV[Workers KV / Cache API<br/>結果的一貫性・グローバル分散]
    Q4 -- No --> D1
    
    Q3 -- 非構造化バイナリ/画像/PDF --> R2[Cloudflare R2<br/>Egress無料の大容量ストレージ]

💡 用語解説コラム

[!NOTE] CAP定理(CAP Theorem) 分散システムにおいては、「一貫性(Consistency)」「可用性(Availability)」「分断耐性(Partition tolerance)」の3つのうち、同時に最大2つしか満たすことができないという定理。CloudflareのKVは可用性と分断耐性を重視したAP型、Durable Objectsは一貫性と分断耐性を重視したCP型の設計思想を持っています。

[!NOTE] エッジのメモリ階層化(Tiered Storage) コンピュータのCPU・キャッシュ・メモリ・ディスクの関係性を、エッジコンピューティング環境(PoPキャッシュ・KV・DO・D1/R2)にそのまま適用したシステム設計。頻繁に読み出されるデータほどネットワーク的・物理的にユーザーに近いノードへキャッシュし、更新頻度や整合性の重い操作ほど集中管理されたレイヤーに委ねます。