🏗️
概念 #データ設計 #データアーキテクチャ #派生データ #Kappa Architecture #DDIA 📚 データ志向アプリケーション設計(DDIA)

データシステムの統合設計

バッチとストリームを統合し、DBを「アンバンドル」して再構成する考え方。DDIAの結論として、派生データとデータフローの全体設計を理解する

定義

本ファイルはDDIAの第12章「データシステムの将来」を整理したもの。個々のデータシステム(DB、キャッシュ、検索インデックス、ストリームなど)を独立したブラックボックスとして扱うのではなく、データフロー全体を一つのシステムとして設計する考え方。

データシステムの現実

アプリケーション

  ├── PostgreSQL(書き込みの正とする)
  ├── Redis(キャッシュ)
  ├── Elasticsearch(全文検索)
  └── Kafka(非同期処理)

問題:
  これらは別々のシステム。どうやってデータを同期するか?
  どれかが故障したとき整合性はどうなるか?

典型的な「泥団子」設計:OLTPにすべて書き込み、定期バッチで他に同期。遅延・整合性不足・スケール困難の三重苦。

派生データ(Derived Data)

真実の源(Source of Truth):
  書き込みが最初に到達するデータ(正規化されたデータ)
  
派生データ(Derived Data):
  真実の源から変換・集計して作られるデータ
  → いつでも再計算できる
  → キャッシュ、検索インデックス、マテリアライズドビューはすべて派生データ

派生データの重要な特性:正しい変換ロジックがあれば、いつでも再構築できる。これがデータシステム設計の「べき等性」。

DBのアンバンドリング(Unbundling)

現代のDB(PostgreSQL等)は内部に多くの機能を統合している:

PostgreSQL の内部:
  ├── WAL(変更ログ)
  ├── インデックス(二次インデックス)
  ├── マテリアライズドビュー
  ├── レプリケーション
  └── フルテキスト検索(tsvector)

「アンバンドリング」とは、これらの機能を専用のシステムに分離し、変更ログ(イベントストリーム)でつなぐ考え方。

PostgreSQL(書き込みの正)
  └── WAL → Kafka(変更ログ)
              ├── → Elasticsearch(検索用派生データ)
              ├── → Redis(キャッシュ用派生データ)
              └── → BigQuery(分析用派生データ)

CDC(Change Data Capture)

DBの変更をリアルタイムにストリームとして流す技術。

ツール:
  Debezium: PostgreSQL/MySQL/MongoDBのWALをKafkaに流す
  Maxwell:  MySQL BinlogをKafkaに流す
  
仕組み:
  DBのレプリケーションプロトコルを模倣してバイナリログを読む
  → アプリを変更せずに変更ストリームが得られる

Lambda Architecture の問題と Kappa Architecture

Lambda Architecture(2014年頃)

Input → バッチ層(正確・遅い)──→ クエリ層(マージ)→ Output
      → スピード層(速い・近似)─┘

問題:同じロジックを2つのシステムで保守しなければならない。結果の整合性管理が複雑。

Kappa Architecture

Input → ストリーム処理層(KafkaのログをReplayして再計算可能)→ Output

Kafkaに全イベントを長期間保持。「再処理が必要になったとき」はコンシューマーグループのオフセットを最初に戻してストリームを流しなおす。バッチ処理が不要になる。

前提:ストリームエンジン(Flink等)が過去データの一括処理も高速にできること。

データフロー設計の原則

不変のイベントログを中心に据える

「状態の変更をイベントとして記録する」という考え方:

状態中心の設計:
  UPDATE orders SET status = 'shipped' WHERE id = 1

イベント中心の設計:
  INSERT INTO events (type, payload) VALUES ('OrderShipped', {orderId:1, ...})
  
イベントから現在の状態を常に再計算できる
→ バグ修正を過去データに遡って適用できる
→ 任意の時点の状態を再現できる(タイムトラベル)

書き込みの境界と読み取りの最適化を分離

書き込み経路:
  単一の信頼できるデータストアへ最初に書く
  
読み取り経路:
  ユースケースごとに最適化されたビューを非同期で生成する
  
→ これはCQRSの物理的な実装そのもの

データメッシュ(Data Mesh)への発展

DDIAの思想を組織設計に拡張したアーキテクチャパターン。

従来の集中型データレイク:
  全チームのデータを中央チームが管理 → ボトルネック

データメッシュ:
  各ドメインチームがデータプロダクトを所有・公開
  → 注文ドメインは「注文イベントストリーム」をプロダクトとして提供
  → 他のチームが自律的に消費・変換

4つの原則:

  1. ドメイン所有のデータ(データの分散所有)
  2. データをプロダクトとして扱う(SLAあり、発見可能)
  3. セルフサービスデータプラットフォーム(インフラの共通化)
  4. フェデレーテッドガバナンス(中央ポリシー + 自律実装)

整合性の考え方の転換

従来の考え方:
  「整合性はDBが保証する」→ 2PCで強制

DDIAの結論:
  「整合性はアプリケーションが設計する」
  → 不変のイベントログが単一の真実の源
  → すべての派生データはいつでも再構築できる
  → 非同期・結果整合で十分なケースが多い
  → 本当に線形化可能性が必要なケースだけZooKeeper等を使う

DDIA シリーズ全体のまとめ

データの保存:
  ← データモデル・ストレージエンジン・エンコーディング

データの分散:
  ← レプリケーション・パーティショニング

データの一貫性:
  ← トランザクション・分散問題・合意

データの処理:
  ← バッチ処理・ストリーム処理

全体の統合:
  ← Saga・CDC・アンバンドリング・Kappa Architecture

関連概念

出典・参考文献

  • Martin Kleppmann, Designing Data-Intensive Applications (2017) Chapter 12
  • Jay Kreps, “Questioning the Lambda Architecture” (2014) — O’Reilly
  • Zhamak Dehghani, Data Mesh (2022) — O’Reilly
  • Debezium Documentation — debezium.io

出典: Martin Kleppmann, 'Designing Data-Intensive Applications' (2017) Chapter 12