# 分散ロックとリース
## 定義
分散ロックは、複数ノードにまたがる系で「ある資源に対して一度に一つのプロセスだけが作業する」ことを保証しようとする機構である。ロック保持者がクラッシュしたまま解放しない事態を避けるため、実運用のロックはタイムアウト付きで発行される。これを**リース(lease)**と呼ぶ。リース保持者は期限内に更新(renew)を続けることで保持を継続し、更新が途絶えれば期限切れとともに他のプロセスが取得できる。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]])
## ゾンビ保持者とフェンシングトークン
リースの安全性は「期限が切れたら旧保持者は書き込みをやめる」という前提に依存するが、この前提は分散システムでは成立しない。GC の stop-the-world、VM のサスペンド、ページフォールト、コンテキストスイッチなどでプロセスは任意の時点で任意の長さ停止しうるうえ、停止したプロセスは自分が停止していたことに気づけない。復帰した旧保持者(ゾンビ)は期限切れを知らないまま書き込みを続け、データを破損させる。ローカルクロックとの比較で有効性を確認するコードは、クロックスキューだけでなくこの一時停止によっても壊れる。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]])
対策が**フェンシングトークン(fencing token)**である。ロックサービスはリースを発行するたびに単調増加する番号を返し、書き込みを受けるストレージ側がその番号を検証する。より新しいトークンによる書き込みを見た後は、古いトークンの書き込みを拒否する。安全性の判定をクライアントの善意でなく資源側の検証に移す点が要諦であり、リーダーレスレプリケーションではトークンをタイムスタンプの上位桁に埋め込むことで同じ効果を得る。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]])
## 横断的知見
- **リースの正しさは合意(consensus)に還元される**。第9章はリース単体の危うさ(ゾンビ保持者)を示し、第10章はリーダー選出・分散ロックが単一値の合意問題と等価であり、コーディネーションサービス([[ZooKeeper]]・[[etcd]]・[[Chubby]])がその実装として提供されることを示す。つまり「安全なリース」を自作しようとする試みは、結局のところ合意アルゴリズムの再実装に行き着く。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]], [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 10 Consistency and Consensus]])
- **フェンシングトークンとべき等性キーは、いずれも「資源側で重複・陳腐化を検証する」という同じ設計原理の別適用である**。フェンシングトークンは陳腐化した書き込みを単調増加番号で弾き、ストリーム処理では Kafka のオフセットを外部データベースへの書き込みに添えて適用済み更新を弾く。どちらもクライアント側の状態管理を信用せず、書き込み先に判定責任を置く。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]], [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 12 Stream Processing]])
- **タイムアウトに基づく障害検知の限界が、そのままリースの限界になる**。第9章はタイムアウト値に「正しい」値が存在しないこと(非有界なネットワーク遅延)を示し、第2章は応答時間がキューイング遅延によりスループット上限付近で急増することを示す。リース期限を短くすれば誤判定によるゾンビが増え、長くすればフェイルオーバーが遅れるという緊張関係は、この 2 つの事実の直接の帰結である。(Source: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]], [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 2 Defining Nonfunctional Requirements]])
## 未解決の問い
- フェンシングトークンの検証をストレージ側が提供しない場合(オブジェクトストアや外部 API など)、どこまで安全な代替が組めるのか。条件付き書き込み(compare-and-set)で代用できる範囲はどこまでか。
- リース期限とフェイルオーバー時間のトレードオフを、実測した遅延分布からどう定量的に決めるか。Phi Accrual 故障検知器のような動的調整はリースにも適用できるか。
- コーディネーションサービスへの依存が単一障害点にならないための運用条件(クォーラムの配置、リージョン跨ぎ時の挙動)は何か。
## 関連
- ソース: [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 9 The Trouble with Distributed Systems]] / [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 10 Consistency and Consensus]] / [[@2026__OReilly__Designing Data-Intensive Applications 2E - Chapter 12 Stream Processing]]
- 概念: [[コーディネーションサービス]] / [[部分故障]] / [[クロック同期と信頼性]] / [[リーダー選出]] / [[分散コンセンサス]] / [[べき等性]] / [[ストリーム処理の耐障害性]]
- 実体: [[ZooKeeper]] / [[etcd]] / [[Chubby]]
## 出典
- Martin Kleppmann and Chris Riccomini, *Designing Data-Intensive Applications*, 2nd Edition, O'Reilly Media, 2026, Chapter 9 "Distributed Locks and Leases", "Fencing off zombies and delayed requests".