「メイン」データベースサーバーと多くの「セカンダリ」サーバー間の双方向同期、特に接続が常に利用可能であるとは限らないと想定して、どのように競合解決を管理しますか?
たとえば、iOSの「データベース」としてCoreDataを使用するモバイルアプリがあります。ユーザーがインターネットに接続せずにコンテンツを編集できるようにしたいと考えています。同時に、この情報はデバイスが接続するWebサイトで入手できます。 2つのDBサーバーのデータが競合している場合、またはどうしたらよいですか?
(私はCoreDataをDBサーバーと呼んでいますが、少し違うことに気づいています。)
この種の問題に対処するための一般的な戦略はありますか?これらは私が考えることができるオプションです:
1。常にクライアント側のデータを優先度の高いものとして使用する
2。サーバー側も同様
3。各フィールドの編集タイムスタンプをマークし、最新の編集を行うことにより、競合を解決するようにしてください
3番目のオプションは、壊滅的なデータ破損の余地を開くと確信していますが。
CAPの定理がこれに関係していることは承知していますが、結果の一貫性だけが必要なので、完全に除外するわけではありませんよね?
関連質問: 双方向データ同期のベストプラクティスパターン 。この質問の2番目の答えは、おそらく実行できないことです。
「どの変更が正しいか」を知るための通常の解決策は ベクトルクロック です。基本的に、データを保持する各リポジトリのカウンターを追跡し、他のすべてのユーザーの状態に対する特定のクライアントのビューが、接続先のピアのビューと異なる場合、変更を拒否します。
答えなければならない大きな問題は、拒否された保存をどのように解決するかです。これは通常、ある種のマージ操作を意味します。
ベクトルクロックはリアルタイムタイムスタンプを使用しないことに注意してください。リアルタイムクロックの同期に関する問題は、少なくともデータの同期と同じくらい困難です。
これは ビザンチン将軍 の問題であり、解決できません。将来のある時点でを保証できない場合は、2つのサーバーを同期することはできません同期することはできません、十分な信頼できる帯域幅があります。同期をすべて一度に実行します。
標準的な方法はないと思います。システムごとに独自のポリシーを使用して競合を解決しています。
コンピューターと電話の2つのデバイス、およびGoogleスプレッドシートを使用してシミュレーションを行い、Googleドキュメントが競合を自動的に処理する方法を確認しました。ここにいくつかのケースがあります:
事例1
事例2
したがって、少なくともGoogleドキュメントサーバーは、作成されたとき(クライアントのタイムスタンプ)とは関係なく、受信した最後のデータをより高い優先度として使用します。また、バックグラウンドで同期するかどうかもテストしましたが、同期していないようです。そのため、競合解決の結果はユーザーに対して透過的です。
一方、GITは競合を自動的に処理しませんが、代わりに、リポジトリの変更を試みていた最後のユーザーに、マージの方法を委任します。
ユーザーがデータを視覚化してフォアグラウンドでのみ同期できる場合は、Googleドキュメントのアプローチを採用します。さもなければ、ユーザーは彼の電話が自動的にWiFiに接続している間、彼が彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼の彼のPCが彼の彼の彼の彼の彼のPCで再編集された後に公開された変更に驚いたかもしれません。
クライアントタイムスタンプアプローチを使用して、最後に編集したものとの競合を上書きします。バックグラウンド同期が必要な場合、クライアントタイムスタンプを信頼でき、望ましくないマージのコストは、ユーザーに希望するバージョンの選択を要求するコストよりも小さくなります。保つ。
それ以外の場合は、GITアプローチを使用します。次のクライアントのポップアップをフォアグラウンドで表示して、保持するバージョンを選択するようにユーザーに要求するか、マージを元に戻す機会を与えます。