プロンプトとシナリオ
グローバルSaaSにおいて、ユーザーが任意のリージョンでプロファイルを編集できるとします。ネットワーク分断中、ヨーロッパと米国の双方が同一ユーザーの更新を受け入れ、復旧後に名前、アバター、タイムゾーン、プライバシー設定でコンフリクトが発生しました。書き込み、レプリケーション、コンフリクト検出、統合、監査、ユーザー復旧を設計し、可用性と一貫性のトレードオフを説明してください。
面接官が見ているポイント
- レコード全体に単一のコンフリクト解決ルールを適用するのではなく、フィールドのセマンティクスに応じて一貫性を分類できるか。
- リージョンルーティング、バージョンメタデータ、レプリケーション遅延、および冪等なリトライを設計できるか。
- 自動統合できないプライバシーやセキュリティ関連のフィールドを適切に処理し、説明可能な結果を提供できるか。
- 復旧、コスト、レイテンシ、データ損失リスクの間で明確なトレードオフを判断できるか。
最初に確認すべき明確化のための質問
- 独立して統合できるフィールドと、プライバシー、アイデンティティ、セキュリティに関わりシリアライズや人間の確認が必要なフィールドはどれか?
- 目標とするのは強一貫性、セッション一貫性、結果整合性のどれか。また、ユーザーが許容できるレプリケーション遅延はどの程度か?
- 1人のユーザーが複数リージョンで能動的に書き込む可能性があるか、それともユーザーまたはテナントごとにホームリージョンを固定できるか?
- 両方のバージョンをどのくらいの期間利用可能な状態にしておく必要があり、ユーザー、サポート、監査担当者には何を表示すべきか?
30秒での回答
フィールドごとに一貫性を分類します。アバターや自己紹介はフィールドレベルの統合を使用し、プライバシーやセキュリティ設定にはより厳密なバージョンチェックを適用します。各書き込みにはユーザーバージョン、リージョン、操作ID、変更されたフィールドを含め、レプリケーションには冪等なイベントを使用します。コンフリクトを減らすためにデフォルトでホームリージョンを設定します。マルチライターが必要な場合は、並行バージョンを検出し、安全なフィールドは自動統合し、機密フィールドにはレビュー用のコンフリクトを作成します。イミュータブルな監査ログを永続化し、ユーザーに見える復旧パスを提供します。コンフリクト率、レプリケーション遅延、ロストアップデート、復旧時間を測定します。
詳細設計
1. フィールドレベルでの一貫性の分類
プロファイルを統合可能なフィールドとセキュリティに敏感なフィールドに分割します。表示名、自己紹介、アバターなどは最終書き込み勝者またはバージョンベースの統合を使用できますが、メールアドレス、MFA、プライバシーの公開設定、アカウント状態などは条件付き書き込み、単一ライター、または人間のレビューが必要になる場合があります。この分類がデータモデル、UI、復旧権限を決定づけるため、行レベルのタイムスタンプだけでは不十分です。
2. シングルホーム、パーティションホーム、またはマルチライターのルーティング選択
最もシンプルな設計は、ユーザーまたはテナントごとにホームリージョンを固定し、近隣のリージョンで読み取りを提供し、障害発生時に一時的に引き継ぐ構成です。ビジネス要件としてマルチライターが必要な場合は、コンフリクト検出と統合コストを受け入れます。ルーティングにはリージョンとバージョンのメタデータを含めるべきです。フェイルオーバーにはリースまたは明示的な引き継ぎエポック(takeover epoch)が必要であり、復旧した古いホームが書き込みを続けて再生(リプレイ)コンフリクトを引き起こすのを防ぎます。
3. バージョン、イベント、および冪等性の設計
フィールドまたはフィールドグループごとにバージョンベクトル、リージョン、論理時刻、最終操作IDを保存します。条件付き書き込みによってクライアントのベースバージョンが依然として有効であることを検証し、リトライは操作IDで重複排除します。レプリケーションイベントには旧バージョン、新バージョン、変更されたフィールドを含めることで、重複、順不同、遅延配信が発生しても、変更が二重に適用されたり上書きされたりしないようにします。
4. コンフリクト検出と自動統合の定義
2つのバージョンは、互いがもう一方を含んでいない場合にコンフリクトとなります。重複しない(disjointな)フィールドは統合可能です。同一フィールドの場合は、ホームリージョン優先、最終ライター、明示的なレビューなどのビジネスルールに従います。実時間(ウォールクロック時間)をユーザーの意図と見なしてはなりません。クロックスキューによって古いコンテンツが勝ってしまう可能性があるためです。すべての統合について、ルール、ソースバージョン、および結果を記録します。
5. プライバシーおよびセキュリティフィールドの保護
プライバシーの公開設定、メールアドレス、ログイン方法、MFAに通常の最終書き込み勝者(last-write-wins)を適用してはなりません。条件付き書き込み、ホームリージョンの承認、または人間のレビューを必須とし、コンフリクト中は公開設定を安全側に倒します。復旧APIはオペレーターを認証し、理由と権限をチェックすることで、「コンフリクトの解決」が権限昇格の抜け穴にならないようにします。
6. 復旧とオブザーバビリティのファーストクラス化
コンフリクト前後のバージョン、イベントチェーン、統合決定を保持し、ユーザーが取り消し(undo)やバージョンの選択を行えるようにします。コンフリクト率、レプリケーション遅延、スタックしたバージョン、ロストアップデート、手動解決時間、リージョン切り替えを監視します。復旧によって2回目の上書きが発生しないよう、リージョン隔離、古いホームの復活、重複イベント、リプレイの演習を実施します。
完全で強力な回答
フィールドごとに一貫性を分類し、プライバシーやセキュリティのフィールドにはより厳格な条件付きルールまたは単一ライターのルールを適用します。近隣での読み取りを伴うユーザーホームリージョンをデフォルトとします。マルチライターが必要な場合は、リージョン、バージョン、操作ID、変更フィールドセットをすべてのイベントに含め、レプリケーションを冪等かつ順序変更に対して安全にします。並行バージョンを検出し、重複しないフィールドを自動統合し、同一フィールドにはビジネスルールまたはユーザーレビューを使用します。決して実時間を意図として扱いません。バージョン、統合ルール、オペレーターを監査ログに書き込み、コンフリクト率、遅延、ロストアップデート、復旧時間を監視し、古いホームの復活や重複イベントのテストを実施します。
よくある失敗パターン
- プライバシーやセキュリティの変更を上書きしてしまう、レコードレベルの単一の last-write-wins ルールを適用すること。
- フィールドの粒度、ストレージコスト、コンフリクト後のユーザー体験を説明せずに「バージョンベクトルを使用する」とだけ述べること。
- 重複、順不同、遅延レプリケーションや古いホームの復活を無視し、復旧中に別の上書きを引き起こすこと。
- 操作ID、監査履歴、ユーザーの取り消しパスを省略し、統合が説明不可能かつ修復不能になること。
- ロストアップデート、コンフリクト率、手動対応コストを測定せずに、可用性とレイテンシのみを議論すること。
フォローアップと発展課題
フォローアップ1:なぜ全面的に last-write-wins を使わないのか?
シンプルで収束しますが、実時間はユーザーの意図を表しておらず、クロックスキューによって古いコンテンツが優先されてしまう可能性があるためです。リスクの低いフィールドであれば許容される場合もありますが、プライバシー、セキュリティ、高価値なコンテンツには条件付き書き込み、ホームライター、または明示的なコンフリクト処理が必要です。
フォローアップ2:ホームリージョンは可用性を損なうか?
リージョン間の書き込みレイテンシが増加し、ホーム障害時の引き継ぎが必要になりますが、コンフリクトと運用の複雑さは大幅に削減されます。テナントごとにホームを選択し、一時的な引き継ぎエポックを提供した上で、データの安全性要件とともに可用性の目標を評価します。
フォローアップ3:UIでコンフリクトをどのように表示すべきか?
フィールド、双方のソース、更新時刻を表示し、なぜ選択が必要なのかを説明します。機密フィールドは安全側を維持し、内部的なリージョン名やデータベースの用語を露出させないようにします。取り消し、リトライ、サポートへの導線を提供し、ユーザーの選択を記録します。
フォローアップ4:レプリケーションが大幅に遅延している場合、どのように読み取るか?
クライアントが鮮度を把握できるように、バージョンまたはリージョンのウォーターマークを返します。重要なフローでの read-after-write(書き込み後の読み取り)は書き込みリージョンにルーティングし、通常の読み取りは結果整合性を受け入れます。遅延がしきい値を超えた場合は、アラートを発報し、リスクの高い変更を制限するか、ユーザーをホームリージョンに誘導します。