プロンプトとコンテキスト
あるシステムに、同じビジネスデータを保存する複数のノードが存在し、それらのノード間でネットワーク分断(パーティション)が発生する可能性があります。一貫性(Consistency)、可用性(Availability)、分断耐性(Partition tolerance)を説明し、それらを注文、在庫、またはソーシャルフィードに適用してください。「2つを選択する」だけで終わらせず、ユーザーに何が表示されるか、どの書き込みが受け入れられるか、そして復旧後にシステムがどのように収束するかを説明してください。
面接官がテストしていること
面接官は、分断時におけるトレードオフを正しく位置付けられるか、一貫性を読み取りの保証、可用性を適時な応答の保証として定義できるか、そして分断耐性を現実の分散ネットワークの制約として扱えるかを見ています。優れた回答は、データベースのラベルで思考を代替するのではなく、ビジネスリスク、縮退動作、競合処理、オブザーバビリティ、リカバリを結び付けて説明します。
明確にすべき質問
- 一貫性は線形化可能(linearizable)、セッションレベル、あるいは一時的に古いデータの許容(stale)のどれを指していますか?
- 可用性において、明示的なリトライ可能エラーを返すことは許容されますか?
- 決済、在庫、キャンセルなど、分断中に停止しなければならない操作はどれですか?
- ローカルキュー、冪等なリトライ、競合のマージ、または人的レビューは許可されていますか?
- リカバリの目標は、データ損失ゼロ、単調な収束、または制限された補償ウィンドウのどれですか?
30秒の回答
CAP定理とは、ネットワーク分断中、システムは強一貫性とすべてのリクエストに対する可用な応答の両方を保証することはできないという原則です。Pは分断が発生しても処理を継続するという制約です。私なら、まず許容できないビジネスエラーを分類します。決済や在庫はリトライ可能エラーを返すかもしれませんが、ソーシャルフィードは古いデータを提供できます。その上で、データベースを恒久的に「CPかつAPの両方」と主張するのではなく、冪等性、競合ログ、リプレイ、リカバリ、メトリクスについて説明します。
ステップごとの詳細な回答
ステップ 1: 3つの用語を定義する
一貫性とは読み取りの保証です。強一貫性は通常、直近に完了した書き込みを読み取ることと説明されます。可用性とは、すべてのリクエストがシステムの規約内で応答を受け取ることを意味します。分断耐性とは、ノード間の通信が失われたり無制限に遅延したりしてもシステムが対処できることを意味します。CAP定理の決定的な前提は、P(分断)が発生したという状況です。
ステップ 2: 分断のタイムラインを描く
東京とシンガポールが通信できない状況を想定してください。双方が同一アカウントに対して相反する書き込みを受け入れ、即座に応答した場合、競合が発生して強一貫性が失われます。片側のみが書き込みを行うか、双方が不確実な操作を拒否した場合、可用性の一部が犠牲になります。データストア名を挙げる前に、まずタイムラインを描いてください。
ステップ 3: ビジネスリスクに応じて挙動を選択する
在庫、決済承認、一意の名前の管理では二重書き込みを避けるべきです。分断中、これらはリトライ可能なステータスを返すか、処理をキューに入れることができます。いいね数、閲覧数、おすすめ機能は、多くの場合、古いデータの読み取りや非同期マージを許容できます。選択基準はAP/CPというスローガンではなく、エラーに伴うコストです。
partitioned:
if operation == payment_or_inventory:
reject_or_queue_with_idempotency_key()
else:
serve_stale_read_and_record_reconciliation()ステップ 4: 書き込みと競合を定義する
リトライ可能な書き込みには、冪等性キーとバージョンを付与します。マルチリージョンの書き込みでは、起点、論理時刻、エビデンスを記録します。リカバリ時には、ビジネスルールに従ってマージ、補償、またはレビューへの送致を行います。不可逆な決済や在庫の競合を、Last-Write-Wins(最終書き込み優先)で覆い隠してはなりません。
ステップ 5: リカバリを説明する
通信が復旧したら、ログとバージョンを交換し、欠落や重複を検知して、リトライ可能なイベントを順序どおりにリプレイします。ユーザーが二重に支払うことがないよう、未解決の注文には明示的なステータスを付与します。リカバリにはレート制限を設け、例外的なレコードにはデッドレターキューや手動処理キューを使用します。
ステップ 6: 検証へと結び付ける
分断の継続時間、拒否率、古い読み取りの経過時間、競合数、補償の成功率、重複リクエストを追跡します。読み取り、書き込み、リトライ、リカバリ、クロスリージョン遅延に対して障害注入を行い、ユーザー向けメッセージが実際の状態と一致していることを検証します。
トレードオフと境界
CAPは永続的な2文字のデータベースラベルではない
選択は分断時における「振る舞い」です。分断が発生していない平常時でも、レイテンシ、コスト、耐久性、運用性が重要です。リクエストレベルの保証に触れずにシステムを「AP」または「CP」と呼ぶことは、設計の本質を隠すことになります。
一貫性の強度を明記する
「一貫性がある」とは、線形化可能性、因果的一貫性、セッション一貫性、あるいは結果的一貫性の収束を意味する場合があります。ノードやプロトコルについて議論する前に、読み取りと書き込みの規約を定義してください。
ロールアウト計画とエビデンス
要件をポリシーに対応付ける
決済、在庫、注文ステータス、検索、ソーシャルカウンターについて、分断時の挙動、ユーザー向けテキスト、リトライの境界、リカバリアクションを文書化します。各保証をAPIおよびデータモデルに対応付けます。
障害訓練を実施する
一方通行の通信パケット損失、遅延、重複メッセージ、部分リカバリをシミュレーションします。最終応答、冪等性レコード、競合キュー、補償処理の会計、アラートを確認し、テスト後にテストデータをクリーンアップして監査ログをレビューします。
よくある間違いとフォローアップ
間違い: CAが分断を乗り越えられると主張する
CAは分断が除外されている場合の一貫性と可用性を説明するものです。実際のノード間システムは、通信障害に対処しなければなりません。
間違い: 可用性を常に「成功」することと同等とみなす
可用性とは適時な応答の保証です。規約が明確である限り、エラー、キューイング、明示的なリトライを返すことは正しいビジネス上の挙動となり得ます。
間違い: すべての競合をLast-Write-Winsで上書きする
決済や在庫の競合には、冪等性、バージョン管理、補償、または人的レビューが必要です。盲目的な上書きはビジネス上の事実を失わせます。
フォローアップ: なぜPは通常避けられないのか?
クロスリージョンネットワークは分断したり、許容できないほど遅延したりする可能性があります。Pを放棄することは、通信障害時に分散サービスを停止することを意味します。
フォローアップ: その選択の妥当性をどのように証明するか?
分断訓練、ユーザーに見える状態、競合および補償のメトリクス、そしてポリシーのロールバック条件を提示します。