『データ指向アプリケーションデザイン』設計判断に効く 6 章だけ抜いた

Martin Kleppmann の 600 ページから設計判断に直結する 6 章だけを要約。レプリケーション、トランザクション、分散システムの落とし穴、整合性、Lambda vs Kappa まで、SVG 図解付きで実問題と紐付けて解説。

📚 『データ指向アプリケーションデザイン』設計判断に効く 6 章だけ抜いた

📖 Martin Kleppmann 著 / オライリー・ジャパン / ¥4,840 — 600 ページの古典から「設計判断に直結する 6 章」だけを要約・図解

📕 『データ指向アプリケーションデザイン』は、分散システムとデータベース設計の「現代の古典」として読まれている。600 ページ、12 章、邦訳の評価も高い。ただ、初学者には厚すぎる。

🎯 本書の真価は 「設計判断のための語彙」を一段深くする ところにある。「データを同期する」が「single-leader か CRDT を選ぶ」になり、「ロックする」が「snapshot isolation で write skew を防ぐ」になる。言葉が変わると、見える地形が変わる

🪜 ここでは、設計判断にすぐ効く 6 章を抜き出した。各章の終わりには 「自分のシステムだと」 ブロックとして、実際に運用しているサービス(個人ダッシュボード や VJ アプリなど)の問題に概念を紐付けてある。同じように手元の問題と本書の概念を結ぶと、本の効き目が桁違いになる。

📘 この記事の読み方(初学者向け)

  • ⏱️ 全部理解する必要はない。各章の冒頭にある「💎 一言で言うと」太字だけを追えば 5 分で全体像が掴める。
  • 📝 専門用語が出てきたら、緑のボックス(用語説明)を読み飛ばさず確認する。
  • 🖼️ 図(SVG)はその章の核心を視覚化したもの。文字を読む前にまず図を眺めるのも有効。
  • 📖 末尾に 用語集 を置いた。途中で詰まったらそこへ飛んで戻るのもアリ。
  • 🚫 「コードを書くわけじゃない人」も対象。実装より、「なぜこの問題が難しいのか」を理解するのが目的。

一.🏛️ 信頼性・拡張性・保守性 — 三本の柱

💎 一言で言うと:システム設計の柱は 信頼性・拡張性・保守性 の 3 本だけ。「故障(fault)」を 「全停止(failure)」に育てない設計が信頼性の核心。

🤔 俺は思うんやけど、ソフトウェアってのはあれや、動いてる時より、壊れる時の方が遥かに正直やで。Kleppmann は冒頭でいきなり、システム設計には三つの柱しかないと言い切る。信頼性(Reliability)、拡張性(Scalability)、保守性(Maintainability)。それ以外は枝葉や、と。

Reliability 信頼性 壊れても動く 🛡️ Scalability 拡張性 負荷に応える 📈 Maintainability 保守性 触れ続けられる 🔧
Fig 1. データシステムを支える 3 本の柱(Chapter 1)

🛡️ 信頼性は「故障しても動く」こと、止まらないことやない。違うで。fault と failure を混同するな、と Kleppmann は言う。

📝 fault(故障)= 部品レベルの不具合(サーバー 1 台が落ちた、ディスクが死んだ、等)
📝 failure(全停止)= システム全体が動かなくなる状態
→ fault は避けられない、failure は設計で防げる

fault(故障)は起きる、必ず起きる。問題は fault が failure(全停止)に化けるか化けへんか、そこだけや。🐒 Netflix が自社サービスをわざと殺す Chaos Monkey を作った理由がここにある。fault を毎日起こしておけば、failure に化ける経路が見える。健康な恐怖や。

💡 fault is unavoidable, but failure is preventable.
故障は避けられんが、全停止は防げる。

💡 自分のシステムだと

📓 個人ダッシュボードで日記を MD ファイルと KV ストア(Cloudflare Workers の Key-Value 簡易データ保管庫)の二箇所に書く構成は、まさにこの「fault が静かに failure に育つ」典型。表面は動いてるが、裏ではストリーク値が時々リセットされる。データベースを単一の真実の源にする移行(SQLite ベースの D1)は、この章の 「fault tolerance を設計の一番底に置く」 原則そのもの。

二.👑 レプリケーション — 独裁・内戦・無政府の三択

💎 一言で言うと:データを複数サーバーに複製する戦略は 3 種類(single-leader / multi-leader / leaderless)。すべてに欠点があり、最善はない。「自分のワークロードに対する最悪が小さい方」を選ぶ。

🔥 レプリケーションの章でこの本はガチで化ける。データを複製する戦略は single-leader、multi-leader、leaderless の三択。Kleppmann の説明が秀逸なのは、全部に欠陥があると最初に宣言するところや。「最善」はない。「あんたのワークロードに対する最悪が小さい方」を選ぶ、それだけや。

📝 レプリケーション(Replication)= 同じデータを複数のサーバーに複製しておく仕組み。冗長化(障害対策)+ 読み取り負荷分散の両方を狙う。
👑 Single Leader 独裁政権 L F F F 書き込み窓口は 1 つ L が死ぬと地獄 PostgreSQL, MySQL ⚔️ Multi Leader 内戦状態 L L L 複数の窓口 conflict 解決が地獄 CouchDB, 旧 Bucardo 🌐 Leaderless 無政府主義 N N N N 全員が書ける quorum で多数決 Cassandra, Dynamo
Fig 2. レプリケーション戦略の三択(Chapter 5) / L=Leader, F=Follower, N=Node

👑 Single Leader は分かりやすい、書き込み窓口が一つ、独裁政権や。シンプル、でもリーダーが死んだ瞬間、失われた書き込みをどう数えるかで地獄が始まる(failover の問題)。

⚔️ Multi Leader は複数の窓口、自由や、でも同じデータを別の窓口で違う値に書いた時、どっちを残す? これは内戦や、調停者がいない(これを conflict resolution、衝突解決と呼ぶ)。

🌐 Leaderless(Cassandra, Dynamo)は窓口を消した、全員が書ける、quorum(定足数)で多数決、これは無政府主義や。「最後の書き込みが勝つ」(Last Write Wins)の罠は、そもそも「最後」を時計でしか測れず、時計は嘘をつく(後述)。

💡 自分のシステムだと

📓 個人ダッシュボードと AI コーディング エージェントが同じ MD ファイルに書く現状は、実質 multi-leader without conflict resolution(衝突解決なしの複数リーダー)。セクション単位で縄張り分けして衝突を回避してるが、これは Kleppmann が 「逃げの戦略、いつか破綻する」 と書くやつや。データベース一元化 = single-leader 化、独裁の方がマシという判断、これが正しい。

三.🔒 トランザクション — ACID は嘘やないが、I は曖昧

💎 一言で言うと:ACID の中で I (Isolation、独立性)が一番曖昧。多くの DB のデフォルト設定では、並行で書いた時のバグ(Lost Update / Write Skew / Phantom)が静かに眠っている。SSI(Serializable Snapshot Isolation)を選べば速くて安全。

🔤 ACID という有名な略語がある。これが何を保証してるか、ちゃんと言える?

📝 ACID = データベースのトランザクション(複数の操作をまとめて 1 つに扱う仕組み)が満たすべき性質
Atomicity(原子性): 全部成功 or 全部失敗、中途半端なし
Consistency(一貫性): データが矛盾しない
Isolation(独立性): 並行に動いても干渉しない
Durability(耐久性): commit したら消えない

🤔 ACID の中で、Atomicity と Durability はまだ意味が固い。Consistency は アプリ側の責任で DB の話やない、と Kleppmann はバッサリ言う。問題は I、Isolation や。これは複数バージョンの「分かったふり」が共存しとる泥沼や。

🛡️ Serializable 完全に逐次実行と等価(SSI で速くなった) 📸 Snapshot Isolation 大半の DB のデフォルト(MVCC) 🔁 Repeatable Read 名前だけで実装が DB ごとに違う ✅ Read Committed PostgreSQL/Oracle のデフォルト ⚠️ Read Uncommitted dirty read 起きる、使うな 下に行くほど速いが、見えてないバグが眠ってる
Fig 3. Isolation level の梯子(Chapter 7)

🪜 isolation level の梯子: Read Uncommitted → Read Committed → Repeatable Read → Snapshot Isolation → Serializable。下に行くほど安全、でも遅い。

😱 ほとんどの DB のデフォルトが Read Committed か Snapshot Isolation で、Serializable じゃない。これは何を意味するか。「並行で書いても辻褄が合う」と無自覚に信じてるアプリのほぼ全てに、再現性の低いバグが眠っとるということや。

📝 並行制御の主なバグ(Isolation が弱いと出る)
Lost Update: 同じ値を 2 人が更新して片方が消える
Write Skew: 個別の更新は OK でも、組み合わせで前提が崩れる
Phantom Read: 同じクエリの結果が途中で増減する

名前だけ覚えても本番で気付けへん。再現させるのが難しい、ログにも出にくい、これが厄介や。

✨ 救いは Serializable Snapshot Isolation(SSI、直列化可能スナップショット隔離)。PostgreSQL がこれを 2011 年に実装した時、業界が静かに進化した。「Serializable は遅い」は古い知識や、SSI なら速い。これだけは覚えておけ。

💡 自分のシステムだと

💾 Cloudflare D1 は SQLite ベース、SQLite は Serializable がデフォルト(WAL モードで)。データベース一元化したら isolation の悩みはほぼ消える、これは D1 を選んだ時点で勝ってる戦い。
💼 業務システム向けの DB を選定する時は、デフォルト isolation level を必ず確認。Read Committed のままで「同時更新が起きる業務」を組むと、本番で初めてバグが顕在化する。

四.👻 分散システムの嘘 — 時計・ネットワーク・プロセス

💎 一言で言うと:複数台で動かす時、無自覚に信じてる前提 3 つは全部嘘。ネットワークは失敗する、時計はズレる、プロセスは止まる。これを前提に設計しないと「本番でしか出ないバグ」が量産される。

🧘 第八章は禅問答のような章や。「あんたが信じてた現実は、全部嘘や」と Kleppmann は淡々と剥がしていく。複数台のサーバーで動かす時、無自覚に信じてる前提がいくつもある。それを 3 つに整理した:

🌐 嘘 ① ネットワーク パケットは消える 遅れる、複製される 順序が入れ替わる → split-brain 嘘 ② 時計 NTP でも数百 ms ズレる VM では数分停止する time-based ID は衝突する → Last Write Wins 死亡 ⏸️ 嘘 ③ プロセス GC で 1 秒止まる page fault で 10 秒 live migration で数分 → 自分の死に気付かない 🪦 これらの嘘を前提に設計しないと、本番でしか出ないバグが量産される
Fig 4. 分散システムの 3 つの嘘(Chapter 8)

🌐 嘘 ①: ネットワークは信頼できない。パケットは消える、遅れる、複製される、順序が入れ替わる。「タイムアウトしたから死んだ」は推測でしかない、生きてる相手にもう一個のリーダーが立ってたら split-brain(分裂脳、同じ役割が 2 つ並行する状態)が起きる

嘘 ②: 時計はもっと嘘つきや。NTP(時刻同期プロトコル)で同期した時計でも、サーバー間で 数百 ms ズレる。仮想化環境ではプロセスが 数分間停止することがある(GC pause、live migration)。「うちの time-based ID は衝突しません」と言うエンジニアの 9 割は嘘つきや、と Kleppmann は半笑いで指摘する。Last Write Wins が壊れる根本原因がここにある

⏸️ 嘘 ③: プロセスは止まる。GC(ガベージコレクション、不要メモリ回収)で 1 秒止まる、ページフォルト(メモリ呼び出しの待ち)で 10 秒止まる、その間 lease(リーダー権の有効期限)が expire してたら、自分が死んでることに気付かないリーダーになる。これが split-brain の本体や。

💡 自分のシステムだと

🎬 VJ アプリの WebGL ループも本質は分散系(GPU と CPU)、時計合わせの問題は requestAnimationFrame でも起きる。
⏱️ サーバーレスの cron job(定期実行)も時刻ベースの判定で重複実行のリスクがある(Cloudflare Workers でも GC pause はある)。
🌍 「時計を信じない設計」は分散系全部の基礎で、この章は表現系にもバックオフィス系にも効く。

五.🔗 整合性と合意 — 「同じものが見える」をどう保証するか

💎 一言で言うと:整合性には強弱がある。linearizability(全員が同じ時間軸で見る)は強いが超高い。causal consistency(原因の前に結果は見えない)で十分なケースが大半。「弱い整合性で済む場面」を見抜くのが目利き

💎 第九章で、Kleppmann は linearizability(線形化可能性)causal consistency(因果整合性) という二つの宝石を取り出す。複数台で動かす時、「みんなが同じものを見てる」をどこまで保証するか — その強度の話や。

🔗 Linearizability 全員が「同じ一本の時間軸」で見る A B C x=1 read x=1 x=2 read x=2 ✅ 全員が同じ順序で観測 遅い、地理分散で絶望的 例: ZooKeeper, etcd, Spanner ⏳ Causal Consistency 「原因の前に結果は見えない」だけ保証 A B C post reply read both ✅ post→reply の順序だけ守る 速い、現実的 例: 大半の分散 DB
Fig 5. Linearizability vs Causal Consistency(Chapter 9)

🔗 linearizability「全員が同じ一本の時間軸で同じものを見る」、強い。でもクソ高い。あらゆる読み書きが調整される必要があり、地理的に分散してたら絶望的に遅い。現代のほとんどの分散 DB は linearizable じゃない(Spanner は例外、TrueTime という GPS + 原子時計のチートで実現)。

causal consistency はもっと弱い、「原因の前に結果は見えない」だけを保証する(例: 投稿の前に返信が見える、みたいなことは起きない)。これで多くのアプリは充分回る。linearizability を諦めて causality だけにするだけで、レイテンシが激減する。これが分かってないと、過剰スペックな DB を選んで金をドブに捨てる。

🤝 合意アルゴリズム(Paxos、Raft)は linearizability を実現する唯一の方法として登場するが、Kleppmann は冷たく言う。「自分で実装するな、ZooKeeper か etcd を使え」。賢者の助言や。

💡 自分のシステムだと

🌐 Cloudflare D1 は linearizable やない(グローバル分散構造上)、でも書き込みは region 内で causality を保証してる。これで充分。
🎚️ VJ で複数端末同期 VJing をやる将来、linearizability が必要になった時、初めて Cloudflare Durable Objects(これは linearizable)を考える、という順番が見える。
💡 「弱い整合性で済む場面」を見抜けるかどうかが、スペックの過剰投資を防ぐ目利きや

六.🌊 バッチとストリーム — 二つは同じものの別の側面

💎 一言で言うと:バッチ処理(夜間集計)とストリーム処理(リアルタイム)は別物に見えて同じ。Lambda(両方並走)は二度手間で罠Kappa(ストリーム一本)が答え。データは「イベントの流れ」、状態はその副産物。

📜 最終章で Kleppmann は Lambda アーキテクチャ(バッチ + ストリーム並列)を冷ややかに退ける。「二回書くな、二つ作るな」。

📝 バッチ(Batch)処理 = 一定量データを溜めてから一括処理(例: 夜間集計)
📝 ストリーム(Stream)処理 = データが届いた順に逐次処理(例: リアルタイム分析)
📝 Lambda アーキテクチャ = 上記 2 つを並列で動かす二段構成
📝 Kappa アーキテクチャ = ストリーム一本、過去データは「再生」して計算

📚 代わりに Kappa アーキテクチャ(ストリーム一本で全部やる) を推す。歴史的に MapReduce(Hadoop)が支配したバッチの世界が、Kafka + Flink/Spark Streaming のストリーム世界に飲み込まれていく流れを、彼は 2017 年時点で予言していた。📅 2026 年の現在、その通りになっとる

⚠️ Lambda アーキテクチャ バッチとストリームを別管理 → 二度手間 📥 Events バッチ層 ストリーム層 合流😩 同じロジックを 2 回書く バグも 2 倍、運用も 2 倍 ✅ Kappa アーキテクチャ ストリーム一本、過去再生でバッチも代替 📥 Events ストリーム 出力 単一の真実、単一の logic 過去計算しなおしたいなら再生する
Fig 6. Lambda vs Kappa アーキテクチャ(Chapter 11/12)

🌊 本質は 「データはイベントの流れであり、状態はその副産物に過ぎない」。これは関数型プログラミングの世界観や(state は fold の結果)。event sourcing(イベント履歴で状態を再構成)、CDC(Change Data Capture、DB の変更を流すパターン)、materialized view(計算結果を物理的に保存) は全部この世界観の派生物や。

💡 自分のシステムだと

📓 個人ダッシュボードの日記 MD/KV 二重管理は、まさに「バッチ(MD)とストリーム(KV)を別々に管理してる Lambda の悪い例」。データベース一元化 = 単一の真実の源、これが Kappa アーキテクチャの精神そのもの。
🚀 一元化を解いた後、「次は event sourcing 的に、習慣チェックのイベントログを DB に貯めて、現在状態を materialized view で計算する」 のが Kleppmann 流の発展や。3 年後の進化方向が、もうこの本に書いてある。


🎯 まとめ — 何が残るか

🪨 俺がこの本から持ち帰った、たった一つの態度はこれや:

💡 「動いてる」を信用するな。「動かなかった時、何が起きるか」を設計しろ。

🧱 Reliability の章から始まり、replication / transaction / distributed systems の章で「動かない経路」を浴びるほど見せつけられ、consensus(合意)の章で「動かなさを前提に動く方法」を学び、最後にバッチとストリームの統合で「壊れた時のリカバリーが安いアーキテクチャ」を教えられる。

📚 600 ページを一気読みする必要はない。困った時に該当章を引く辞書として、3 年は使える。設計判断で迷ったら、まずこの本を開く — それだけで「自分が今、何の問題を解いているのか」が一段クリアになる。

🔑 補足: まとめで使った CRDT(Conflict-free Replicated Data Type、衝突しない複製データ型)は本書 Chapter 5 で扱われる、leaderless 環境での conflict resolution を成立させる仕掛けや。Google Docs の同時編集や Figma のリアルタイム共同編集の裏側にいる主役の一人。

📖 買え。 🪑 読め。
🚧 自分のシステムで一番ヤバいやつ(俺の場合は二重書きの race condition)に着手する前に 第 5・7・9 章だけは読め。
📚 残りは 辞書として三年使え

📖 用語集 — 本記事に登場する主要 30 語

読みながら詰まったらここへ戻ってきてください。本書を読む際にも参照になります。

🔤 ACIDトランザクションが満たすべき性質: Atomicity(原子性)/ Consistency(一貫性)/ Isolation(独立性)/ Durability(耐久性)。
📦 トランザクション複数の DB 操作をまとめて 1 つの単位として扱う仕組み。「全部成功 or 全部失敗」を保証する。
🔁 レプリケーション (Replication)同じデータを複数のサーバーに複製して持つこと。冗長化 + 読み取り負荷分散の両方が目的。
👑 Single Leader書き込み窓口が 1 台に集中する構成。シンプルだがリーダー障害時の処理が難しい。PostgreSQL/MySQL 標準。
⚔️ Multi Leader書き込み窓口が複数の構成。同じデータを別の窓口で書くと衝突するため、解決ロジックが必要。
🌐 Leaderlessリーダーを持たず、全ノードが書き込みを受け付ける構成。多数決(quorum)で正しい値を決める。Cassandra など。
⚖️ Conflict Resolution複数の場所で同じデータが書き換えられた時、どちらを残すか決める処理。「衝突解決」。
🗳️ Quorum(定足数)分散環境で「多数決」する時の必要票数。3 台なら 2 票で決定、など。
🏁 Last Write Wins「最後の書き込みが勝つ」ルール。時計に依存するため、時計のズレで壊れる(下記参照)。
🧩 CRDTConflict-free Replicated Data Type。複数箇所で書いても自動的に矛盾が解消される特殊なデータ型。Google Docs / Figma の同時編集の裏側。
🪜 Isolation Levelトランザクションが他のトランザクションからどれだけ分離されるかの強度。弱い順に Read Uncommitted → Read Committed → Repeatable Read → Snapshot Isolation → Serializable。
📸 Snapshot Isolationトランザクション開始時点のデータ状態(スナップショット)を見続ける方式。多くの DB のデフォルト。
🛡️ Serializable最強の Isolation Level。並行実行の結果が「順番に 1 個ずつ実行した時」と同じになる。
✨ SSISerializable Snapshot Isolation。Snapshot Isolation の速さで Serializable の安全性を実現する技術。PostgreSQL が 2011 年に実装。
🗂️ MVCCMulti-Version Concurrency Control。データの複数バージョンを内部に持って並行性を上げる仕組み。
📝 WALWrite-Ahead Logging。書き込みを「先にログ」として記録してから本体に反映する手法。耐障害性の基礎。
❌ Lost Update2 人が同じ値を更新した時、片方の更新が消える並行制御バグ。
🎭 Write Skew個別の更新は OK でも、組み合わせ全体で前提が崩れる並行制御バグ。Snapshot Isolation でも起きる。
👻 Phantom Read同じクエリを再実行した時、結果の行が増減しているバグ。
🪓 Split Brain「分裂脳」。同じ役割(リーダーなど)が同時に 2 つ立つ状態。データ破損の典型原因。
⏰ NTPNetwork Time Protocol。サーバーの時計を同期するプロトコル。同期しても数百 ms のズレは残る。
⏸️ GC Pauseプログラムが不要メモリを回収する間、処理が止まる時間。1 秒〜数秒止まることもある。
🎫 Lease(リース)「自分がリーダーである権利」の有効期限。GC Pause で更新できないと、自分の死に気付かずデータを書き続けることがある。
🔗 Linearizability「線形化可能性」。全員が同じ一本の時間軸で同じものを見ることを保証する強い整合性。実装コストが高い。
⏳ Causal Consistency「因果整合性」。原因より先に結果が見えないことだけを保証する弱めの整合性。多くのアプリには十分。
🤝 Paxos / Raft分散環境で複数ノードが「同じ決定」に到達するための合意アルゴリズム。Raft は Paxos の理解しやすい改良版。
🦁 ZooKeeper / etcd分散システムの調整役として広く使われるツール(設定管理 / リーダー選出 / ロックなど)。Raft / Paxos を実装している。
⚠️ Lambda Architectureバッチ層とストリーム層を並列に動かす二段構成。同じロジックを 2 回書く必要があり保守が辛い。
🌊 Kappa Architectureストリーム処理一本で完結させる構成。過去データは「再生」して計算しなおす。Lambda の代替。
📜 Event Sourcing「現在の状態」を保存するのではなく「変化したイベント全部」を保存する方式。状態は履歴を fold して計算する。
📡 CDCChange Data Capture。DB の変更をリアルタイムでイベントストリームに流すパターン。マイクロサービス間連携で活躍。
🪞 Materialized Viewクエリの結果を物理的に保存しておくテーブル。読み取り高速化に使う。
💥 Fault vs Failurefault = 部品レベルの故障(避けられない)/ failure = システム全停止(設計で防げる)。区別が信頼性設計の核心。
🐒 Chaos MonkeyNetflix が作ったツール。本番サーバーを意図的にランダムで殺し、システムが「fault に強い」かを毎日テストする。

📕 書誌情報

『データ指向アプリケーションデザイン — 信頼性、拡張性、保守性の高い分散システム設計の原理』
Martin Kleppmann 著 / 斉藤 太郎 監訳 / 玉川 竜司 訳
オライリー・ジャパン / 2017 年 / 600 ページ / 4,840 円(税込)
原題: Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems

🤖 Claude Opus 4.7 (claude-opus-4-7) / 📅 2026-04-25

💡 この記事の内容を、業務に組み込んでみませんか?

福岡で中小企業の AI 導入支援・業務自動化・技術顧問をやっています。
議事録の自動化、業務スクリプト、システム開発まで。
30分で「何から始めるべきか」を一緒に整理します。