第8章:信頼性は“崩れる前提”で考えるもの──完璧を捨てる技術
第8章:信頼性は“崩れる前提”で考えるもの──完璧を捨てる技術
『データ指向アプリケーションデザイン(DDIA)』第8章を読んだメモです
崩れない設計より「崩れても壊れない設計」へ
信頼性をどう設計するか、自分の経験と照らして読み解きました
多くのシステムは「壊れないことを前提」に作られている
でも現実はこう:
- コンピューターは物理。壊れるしズレる
- 人間は“常に10%間違える処理”なんて信じたくない
だから「壊れるときは盛大に壊れる設計」になりがち
壊れる前提に立つ設計とは、人間の“壊れなさ信仰”と戦うことでもある
信頼性とは「弱い入力」をどう扱うか
TCPが信頼性を担保するのは、「信頼できないネットワークをどう補完するか」に全振りしているから
アプリケーション側でも同じ
ユーザー入力という“信用ならない外部入力”を:
- バリデーションして
- リトライ促して
- それでもダメなら破棄 or フォールバック
という設計にする必要がある
信頼性を作るとは、“信用できない世界”と折り合う設計のこと
ネットワークは「気まぐれで、物理的で、嘘をつく」
- 地球の気候にも影響される
- 光速すらボトルネックになる
- VMの壁を越えるたびにレイテンシが積まれる
- ZoomやゲームでラグるのもUDPの性質ゆえ
つまり、ネットワークは「がんばってるけど信用ならん奴」
タイムアウトと指数バックオフは基本中の基本
でもそれが万能かというと…?
- クラウドが死んでたらリトライ先がそもそもない
- エラー画面の設計がなければ“失敗”で終わる
- 死活監視してても「確実には死んだ」と言えない
部分的な故障を“なんとなく生きてる”ように見せる仕組みが必要
「時刻」は絶対じゃない、“目安”にすぎない
- タイムスタンプは不確実
- スノーフレークIDもズレることがある
- Spanner の TrueTime は「信頼できる幅」を定義して commit している
つまり:
正しい時刻がわからないなら、正しい範囲を作ればいい
という柔らかい整合性の哲学
真実はひとつ…ではなく、“だいたいひとつ”
分散システムでは「多数決による故障判定」が基本:
- 本当に死んでるかどうかは誰にもわからない
- 「たぶん死んでるっぽい」を集めて判断するしかない
これがクラッシュ検出と信頼性の“実際”
ビザンチン障害と、信頼性の限界点
- 嘘をつくノード
- 外部スパイ
- 意図的な混乱
こうなると、公開鍵や署名での検証くらいしか対抗策がない
“正しく動くように見える嘘つき”がいたら手に負えない
ここに対抗するには「限界を知って割り切る設計」が重要
部分同期モデルこそが現実
完全同期・非同期はあくまで理論モデル
現実のシステムは:
- 一部のコンポーネントが同期
- 他は非同期に動き
- それでも整合性がとれるように補正を入れる
という“ちぐはぐで合理的”な世界で動いている
その調整設計こそがエンジニアリング
設計とは「壊れ方を選ぶ」行為
完全性の保証には、必ず何かの犠牲がある:
- GCによる停止
- リアルタイム処理による可読性・スループットの低下
- 並列性の代償としての整合性の崩壊リスク
どこまで壊れていいのか?何を守るのか?
それを決めるのが設計
図8: 信頼性ループ ── 失敗から学び、次の失敗を小さくするサイクル
✍️ まとめ:信頼性は“抽象のスコープ設定”で生まれる
設計とは抽象のスコープをどう絞るか
- DDDもOOPもアルゴリズムも、現実を一部だけ扱う技術
- 複雑さを削るための道具であって、万能ではない
だから信頼性も「どこまで信じて、どこからは諦めるか」で決まる
完璧な正解を追いかける行為ではなく、制約の中で“知的折り合い”をつける作業なのだ
💡 設計Tips
- ネットワークや入力は信用しない前提で設計する
- タイムアウトとフォールバックは必須(リトライだけで戦わない)
- 時刻は「範囲」で扱う思想が必要
- 故障判定は“だいたいの多数決”でしかできない
- 信頼性は“壊れるものとどう付き合うか”で決まる
Discussion