■ 1. クラウドネイティブDBの定義
- CNCF Cloud Native Definition v1.1 に基づき、近代的でダイナミックな環境において以下を実現するDBを指す
- 動的にスケールできる能力
- 回復性・管理力・可観測性のある疎結合システム
- インパクトのある変更を最小限の労力で行える能力
- CNCF定義の3項目は、DBでは4つの実装パターンに分解される
- スケーラビリティ: 動的スケーリング / Scale to Zero
- 疎結合の実現: Compute / Storage 分離
- 管理力・回復性: マネージド運用 / 自己修復
- DB固有の整合性: 分散合意 + 時刻順序
■ 2. クラウドネイティブDBが克服すべき3つの壁
- 壁①書き込みボトルネック:
- 単一プライマリでの書き込み頭打ち
- 単一障害点(SPOF)のリスク
- 手動シャーディングの運用負荷
- トレードオフ: 運用負荷
- 壁②I/O負荷とスケーリング:
- 従来RDBのアーキテクチャ限界
- 可用性と拡張性の両立困難
- ハードウェア故障時のリカバリ負荷
- 高速なスケールアウトが不可能
- トレードオフ: ネットワーク帯域
- 壁③分散下の強い一貫性:
- ノードのクラッシュの復旧
- 不可避な「時計のズレ」
- レプリケーションラグの影響
- イベント順序の非決定性による不整合
- トレードオフ: レイテンシ
■ 3. 第1章: 書き込みスケールの壁 ─ シャーディングの系譜
- ボトルネックの要因: DISK IO / CPU(ロック競合、計算)/ 帯域 / RAM の物理的上限(単一ノード性能上限)
- 解決策: データを複数ノードに分散し、書き込みを並列化する(シャーディングによるスループットの水平スケール)
- シャーディングの配置場所による設計パターン:
- 手動シャーディング:
- アプリケーション側でシャードキーを管理する原始的な水平分割
- 得たもの: 書き込みスケール、データ局所性、障害影響範囲の分離
- 失ったもの: クロスシャードJOIN、分散トランザクション、透過的なリバランス
- 運用上の痛み: シャード追加・リバランスが手作業で重い、アプリ側にデータ配置ロジックが漏れる、シャードキー変更が事実上不可能
- マネージドシャーディング:
- ミドルウェア・プロキシ層が複雑なシャーディング構造を抽象化
- 代表例: Vitess(MySQL前段)、Citus(PostgreSQL拡張)、Aurora PostgreSQL Limitless
- 進化点: シャード管理の自動化、透過的なクエリルーティング、リシャーディングの簡素化
- 重要な制約: ミドルウェアで隠蔽しても、データ局所性の設計は不可欠、ノード間を跨ぐJOINや集計処理のパフォーマンス劣化が発生
- シェアードナッシング:
- 各ノードが独自のCPU/メモリ/ディスクを保持し、運用中に自動リバランスを実行
- 代表例: Spanner、CockroachDB、TiDB、YugabyteDB
- 利点: ノード追加による水平スケール、自動でのリバランス(Split, Merge)
- 課題: 特定ノードへの負荷集中(ホットスポット)、通信オーバーヘッドによるレイテンシ、分散クエリの効率低下
- 設計指針の適用:
- 制約の明示化: シャードキー設計=「データ局所性」を明示的に設計に組み込む
- 責任の所在の移動: アプリ → ミドル → DB自身(隠蔽の度合いが向上)
- トレードオフの選択: 分散処理(JOIN/トランザクション)やリバランスコストの受容
- 残る課題: シャーディングでも解決しない1ノード内のI/O負荷限界、リカバリ・ノード追加の高いコスト、より高速で柔軟なスケーリングの必要性
■ 4. 第2章: I/O負荷とスケーリングの壁 ─ ログ適用型ストレージの系譜
- 従来DBの問題: 「単一サーバー前提アーキテクチャ」における多すぎる責務がI/O増幅を招き、スケーリングを困難にする
- 多すぎる責務: ログ生成/ページ更新、チェックポイント作成、レプリケーション/バックアップ、リカバリ
- I/O増幅の発生: 1更新が複数の物理I/O(ログ生成、バックアップ用ログの二重書き、フルページ書き込み、データページ書き出し)に
- 負の連鎖(悪循環): ノード追加には重いデータコピーが必須、高負荷時にスケールアウトするとコピー処理でさらに負荷が上がる矛盾
- 解決策: コンピュート/ストレージの分離 と ログ適用型ストレージ の組み合わせ
- コンピュート/ストレージの分離:
- 単一サーバー前提を解く第一歩
- スケール操作からデータコピーを切り離す
- ステートレス化されたコンピュート層で柔軟なスケールを実現
- ログ適用型ストレージ("Log is the DB"):
- コンピュート層: redo log recordだけを生成・送信
- ストレージ層: redo logからページを再構築
- redo処理 / fault-tolerant storage / self-healing / quorum をストレージサービス側に集約
- 分離する理由:
- ノード追加コストの解消: 共有ストレージ参照のみで起動、ノード追加が数時間 → 数秒に短縮
- きめ細かなスケーリング: コンピュートをステートレスにすることで分単位の弾力性を実現、Scale to Zeroも対応可能(Aurora Serverless / Neon)
- 非対称なリソース消費: コンピュートはスパイク型、ストレージは単調増加型、別々にスケールすることが合理的
- ログ適用型ストレージの効果(Aurora SIGMOD 2017より):
- Network I/O削減: 7.7倍
- Throughput向上: 35倍
- 業界横断のパラダイム:
- Aurora(AWS、2014〜): log-applied storageの元祖、6-way/3 AZ、Limitlessで水平スケール、DSQLでmulti-region active-active
- Neon(Serverless): Pageserver + Safekeeper構成、Paxos-based consensus、Branching / Scale to Zero、秒単位の課金体系
- AlloyDB(Google Cloud、2022): Paxos + HTAP、内部にLog Processing Service(LPS)、カラムナエンジンでHTAP対応、Omniでオンプレミス環境にも対応
- 設計指針の適用:
- 制約の明示化: I/O増幅を「redo logのみ送信 + ストレージ側で実体化」として明示化
- 責任の分離: computeとstorageを別の層として切り離す
- トレードオフの選択: ネットワーク帯域 / quorum待ちレイテンシ
- 残る課題: コンピュートを分離しても、複数ノードに跨る整合性・順序づけは依然として別次元の難題
■ 5. 第3章: 強い一貫性の壁 ─ 分散合意とグローバル順序づけの系譜
- 課題: 分散すると、複数ノード間での「合意」と「順序づけ」が必要
- replication順序: レプリカ間でログ順序を一致させる(= 分散合意)
- transaction順序: 実時間の順序づけ(= グローバル時刻)
- 両方解かないと強い一貫性には到達しない
- 2PCの問題点:
- coordinator が死ぬと停止し、残ったworkerはcommit/abortを判断できない
- 不確定状態のままworkerはロックを保持し続ける(連鎖的にハング)
- 死んだと思ったcoordinatorが復活すると不整合が起きる
- 分散合意(Paxos / Raft)が解決すること:
- 自動フェイルオーバー: リーダー障害時の自動再選出
- データの自動同期: ログレプリケーション
- 一貫性の維持: リーダー経由 / コミット済みは必ず読める
- ネットワーク分断耐性: 過半数側が継続、少数派は停止
- Paxos系: Spanner(Multi-Paxos)/ Neon
- Raft系: CockroachDB / TiDB(TiKV)/ YugabyteDB / etcd / Consul
- 分散DBの中核処理は時刻に依存する:
- 分散MVCC: 各ノードが独立にIDを発番できないため、グローバルなタイムスタンプが必要(Spanner: TrueTime、CRDB/Yuga: HLC、TiDB: TSO)
- Snapshot Isolation: 全ノードで「どの時刻か」の合意が必要
- Read at Timestamp / Time Travel: クロックスキューが大きいと整合性が壊れる
- 時刻同期の難しさ:
- ノード間のクロックは必ずズレる(NTP: ms級 / PTP: μs級)
- ネットワーク通信のラグ(RTT)が存在する
- 「どのトランザクションが先か」を全ノードで合意するのは本質的に困難
- 各NewSQLのアプローチ比較:
- Spanner(Google、2012): TrueTime API + Commit Wait
- 時刻を[earliest, latest]の区間として定義し、クロックの不確実性(ε)をAPIとして明示的に露出
- Commit Waitによりε msだけ待機することで実時間順序 = タイムスタンプ順序を保証(External Consistency)
- トレードオフ: commit wait(代償: ε msのwait / strict serializable)
- CockroachDB(2015〜): HLC(Hybrid Logical Clock)、汎用NTP環境でも因果順序を追跡可能
- strict serializableは提供しない、causal reverse異常を許容
- clock offset平均値が400msを超えると自己shutdown(Fail-Safe設計)
- トレードオフ: retry + causal reverse許容
- TiDB(PingCAP、2016〜): TSO(Timestamp Oracle)+ PD(Placement Driver)による集中型タイムスタンプ発番
- 順序づけがサービス化(集中管理)され、HLCのような複雑な時刻ズレ管理から解放される
- トレードオフ: PD取得待ち(代償: Snapshot Isolation / cross-DCレイテンシ)
- YugabyteDB(2016 / ClockBound 2025): HLC + ClockBound統合
- v2025.2 LTSでAWS ClockBound統合、TrueTimeに近い区間APIを活用、PHCによりμs級skewを実現
- ClockBound有効時: Transaction Latency最大3倍短縮、Throughput 2倍向上(RF=3 / geo-distributed条件)
- トレードオフ: クラウド時刻API(代償: AWS/GCP限定 / Serializableまで選択可)
- Aurora DSQL(AWS、2025 GA): Time Sync Service + Journal
- トレードオフ: OCC retry(代償: 競合時のretry / region-set内)
- 設計指針の適用:
- 制約の明示化: 時刻不確実性をAPIに組み込む
- 責任の分離: 時刻管理を分離する
- トレードオフの選択: commit waitによる書き込みレイテンシ / OCCによるリトライレイテンシ / TSO取得レイテンシ
■ 6. 3章の統合: NewSQLへの帰結
- 3つの壁すべてを解くのがNewSQL
- 壁①のみ解く → シャーディングDB(Vitess / Citus)
- 壁②のみ解く → クラウドRDB(Aurora / AlloyDB / Neon)
- 壁③のみ解く → 分散KVS(etcd / Consul)
- 壁①②③すべて解く → NewSQL
- 5つのNewSQLの3軸での比較:
- Spanner: auto split/merge / Colossus + Paxos / TrueTime + Commit Wait
- CockroachDB: range分割 / local + Raft / HLC
- TiDB: region分割 / TiKV + Raft / TSO / PD
- YugabyteDB: tablet自動分割 / DocDB + Raft / HLC + ClockBound
- Aurora DSQL: region-set / Journal + 分離 / Time Sync Service + OCC
- 同じ"NewSQL"でも、3軸の選び方で性格が変わる
■ 7. 応用: 最適な選択基準の策定
- 壁①書き込みスケールを優先する場合:
- MySQL互換で大規模分割 → Vitess / TiDB
- PostgreSQL互換で水平分割 → Citus / Aurora Limitless
- 壁②I/O負荷・運用負荷を優先する場合:
- 単一region・運用簡素化 → Aurora / AlloyDB
- Scale to Zero・コスト効率 → Neon / Aurora Serverless
- 壁③強い一貫性を優先する場合:
- 単一クラウドで強整合 → Aurora DSQL / Spanner
- マルチクラウド対応 → CockroachDB / YugabyteDB / TiDB
- 経験則: 3つの壁すべてが本当に必要 → NewSQL系が見合う、2つ以下しか必要ない → マネージドDBで十分
- 3指針×5つの問い:
- Q1(制約の明示化)何をスケールするか: 書込み大量 → Limitless / Vitess / NewSQL系、読込中心 → Aurora
- Q2(責任の分離)どこにデータ配置するか: 単一region → Aurora / Spanner、全大陸 → Spanner、2region active → DSQL
- Q3(トレードオフの選択)どの整合性か: strict serializable → Spanner / DSQL、SI → TiDB / Yuga、RCで十分 → Aurora
- Q4(トレードオフの選択)何を犠牲にするか: commit wait許容 → Spanner、retry許容 → DSQL、causal reverse許容 → CockroachDB、TSO待ち許容 → TiDB
- Q5(責任の分離)誰が複雑性を吸収するか: ベンダー全任せ → マネージド、自社運用 → OSS
- 同じ問いはメッセージングなどあらゆる分散システムに適用可能
- 大前提: 分散システムを作らない、制約を解決するために本当に分散システムが必要か十分に考慮すること
■ 8. まとめ: 分散システムの設計指針
- クラウドネイティブDBの進化は「制約 ↔ 分離 ↔ トレードオフ」という設計判断の積み重ねである
- 3つの壁とその克服:
- 壁①書き込みボトルネック・運用負荷 → シャーディング、そして自動化(アプリ → ミドルウェア → DB自身)
- 壁②I/O負荷・スケーリング → ストレージ分離、ストレージインテリジェント化(ログ適用型ストレージ)
- 壁③分散環境下の強い一貫性 → 分散合意アルゴリズム + 一貫した時刻の管理(commit wait / OCC retry / TSO待ち / クラウド時刻API)
- 選択は「最強」ではなく「最適なトレードオフ」
- 自分の要件で要らない機能の代償を払わない
- 分散システム設計の3指針:
- ①制約を明示化する: 暗黙の前提を捨て、API・構造・境界として「可視化」する
- ②責任を分離する: compute / storage、replication / transaction... 層をまたぐ責任を切る
- ③トレードオフを選ぶ: 何を守り、何を犠牲にするか意図的に決める