質問

クライアントとサーバーの同期パターンが必要だと感じています。しかし、私は完全にグーグルアップすることに失敗しました。

状況は非常に単純です。サーバーは中央ノードであり、複数のクライアントが同じデータに接続して操作します。データはアトムに分割できます。競合が発生した場合、サーバー上にあるものが優先されます(ユーザーが競合を解決できないようにするため)。潜在的に大量のデータがあるため、部分同期が推奨されます。

そのような状況のパターン/良い慣習はありますか、または知らない場合-あなたのアプローチは何ですか?

以下は、私が今それを解決するために考えている方法です: データと並行して、修正ジャーナルが保持され、すべてのトランザクションにタイムスタンプが付けられます。 クライアントが接続すると、最後のチェック以降のすべての変更を統合形式で受信します(サーバーはリストを調べ、削除が続く追加を削除し、各アトムの更新をマージします)。 出来上がり、私たちは最新です。

代替方法では、各レコードの変更日を保持し、データ削除を実行する代わりに、削除済みとしてマークします。

何か考えはありますか

役に立ちましたか?

解決

分散変更管理の仕組みを確認する必要があります。 SVN、CVS、およびデルタ作業を管理する他のリポジトリを見てください。

いくつかのユースケースがあります。

  • 変更を同期します。これには、変更ログ(またはデルタ履歴)アプローチが適しています。クライアントは、デルタをサーバーに送信します。サーバーは、デルタを統合してクライアントに配布します。これは典型的なケースです。データベースはこれを「トランザクションレプリケーション」と呼びます。

  • クライアントの同期が失われました。バックアップ/復元またはバグが原因です。この場合、クライアントは、デルタを経由せずにサーバーから現在の状態を取得する必要があります。これは、マスターからディテールへのコピーであり、デルタとパフォーマンスがひどいものです。それは一度限りのものです。クライアントが壊れています。これを最適化しようとせず、信頼できるコピーを実装するだけです。

  • クライアントは疑わしい。この場合、クライアントをサーバーと比較して、クライアントが最新であり、デルタが必要かどうかを判断する必要があります。

すべての変更に順番に番号を付けるデータベース(およびSVN)設計パターンに従う必要があります。このようにして、クライアントは同期を試みる前に些細な要求(「どのリビジョンを使用する必要がありますか?」)を行うことができます。そして、それでも、クエリ(「2149以降のすべてのデルタ」)は、クライアントとサーバーが処理するのがとても簡単です。

他のヒント

チームの一員として、データの同期を伴う非常に多くのプロジェクトを行ったため、この質問に答える能力が必要です。

データの同期は非常に広い概念であり、議論するのは多すぎます。利点と欠点を備えたさまざまなアプローチを網羅しています。同期/非同期、クライアント/サーバー/ピアツーピアという2つの観点に基づいた可能な分類の1つを次に示します。同期の実装は、これらの要因、データモデルの複雑さ、転送および保存されるデータ量、およびその他の要件に大きく依存します。そのため、特定の場合には、アプリの要件を満たす最も単純な実装を選択する必要があります。

既存の既製のソリューションのレビューに基づいて、同期の対象となるオブジェクトの粒度が異なるいくつかの主要な同期クラスを説明できます。

  • ドキュメントまたはデータベース全体の同期は、Dropbox、Google Drive、Yandex.Diskなどのクラウドベースのアプリケーションで使用されます。ユーザーがファイルを編集して保存すると、新しいファイルバージョンが完全にクラウドにアップロードされ、以前のコピーが上書きされます。競合が発生した場合、ユーザーが関連性の高いバージョンを選択できるように、両方のファイルバージョンが保存されます。
  • キーと値のペアの同期は、単純なデータ構造のアプリで使用できます。変数はアトミックであると見なされます。つまり、論理コンポーネントに分割されていません。このオプションは、値とドキュメントの両方を完全に上書きできるため、ドキュメント全体の同期に似ています。ただし、ユーザーの観点からは、ドキュメントは多くの部分で構成される複雑なオブジェクトですが、キーと値のペアは短い文字列または数字にすぎません。したがって、この場合、最後に変更された値であれば、より適切な値を考慮して、より簡単な競合解決の戦略を使用できます。
  • ツリーまたはグラフとして構造化されたデータの同期は、データの量が更新ごとにデータベース全体を送信するのに十分な量である、より高度なアプリケーションで使用されます。この場合、競合は個々のオブジェクト、フィールド、または関係のレベルで解決する必要があります。主にこのオプションに焦点を当てています。

それで、この記事に知識を取り入れました。これは、トピック=&gtに興味があるすべての人にとって非常に役立つと思います。コアデータベースのiOSアプリでのデータ同期( http://blog.denivip.ru/index.php/2014/04/data-syncing-in-core-data-based-ios-apps/?lang=en

本当に必要なのは、運用変換(OT)です。これは多くの場合、競合にも対応できます。

これはまだ活発な研究分野ですが、さまざまなOTアルゴリズムの実装があります。私はこのような研究に何年も関わってきましたので、このルートがあなたに興味があるかどうかをお知らせください。関連するリソースを紹介させていただきます。

質問は明確ではありませんが、楽観的ロックを調べました君は。 サーバーが各レコードに対して返すシーケンス番号を使用して実装できます。クライアントがレコードを保存しようとすると、サーバーから受信したシーケンス番号が含まれます。シーケンス番号が、更新を受信した時点でデータベースにあるものと一致する場合、更新が許可され、シーケンス番号が増分されます。シーケンス番号が一致しない場合、更新は許可されません。

約8年前にアプリ用にこのようなシステムを構築しましたが、アプリの使用量の増加に伴って進化したいくつかの方法を共有できます。

あらゆるデバイスからのすべての変更(挿入、更新、削除)を「履歴」に記録することから始めました。表。たとえば、「連絡先」で誰かが電話番号を変更した場合、テーブルの場合、システムはcontact.phoneフィールドを編集し、action = update、field = phone、record = [contact ID]、value = [new phone number]の履歴レコードも追加します。その後、デバイスが同期するたびに、最後の同期以降の履歴アイテムがダウンロードされ、ローカルデータベースに適用されます。これは「トランザクションレプリケーション」のように聞こえます。上記のパターン。

1つの問題は、異なるデバイスでアイテムを作成できるときにIDを一意に保つことです。これを開始したとき、UUIDを知らなかったため、自動インクリメントIDを使用し、中央サーバーで実行される複雑なコードを記述して、デバイスからアップロードされた新しいIDを確認し、競合がある場合は一意のIDに変更し、ローカルデータベースのIDを変更するようソースデバイスに指示します。新しいレコードのIDを変更するだけでもそれほど悪くはありませんでしたが、たとえば、連絡先テーブルに新しいアイテムを作成し、イベントテーブルに新しい関連アイテムを作成した場合、外部キーも必要になります。確認して更新します。

やがてUUIDでこれを回避できることがわかりましたが、その頃にはデータベースがかなり大きくなり、UUIDを完全に実装するとパフォーマンスの問題が発生するのではないかと心配しました。そのため、完全なUUIDを使用する代わりに、ランダムに生成された8文字の英数字キーをIDとして使用し始め、競合を処理するために既存のコードをそのまま残しました。私の現在の8文字のキーとUUIDの36文字の間のどこかに、不必要な膨張なしに競合を排除するスイートスポットがなければなりませんが、競合解決コードを既に持っているので、それを試すことは優先事項ではありませんでした。

次の問題は、履歴テーブルが他のデータベース全体よりも約10倍大きいことでした。これにより、ストレージが高価になり、履歴テーブルのメンテナンスが面倒になる場合があります。テーブル全体を保持することで、ユーザーは以前の変更をロールバックできますが、やり過ぎのように感じ始めました。そこで、同期プロセスにルーチンを追加し、デバイスが最後にダウンロードした履歴アイテムが履歴テーブルに存在しない場合、サーバーは最近の履歴アイテムを提供せず、代わりにすべてのデータを含むファイルを提供しますそのアカウント。次に、cronジョブを追加して、90日より古い履歴項目を削除します。つまり、ユーザーは90日未満の変更を引き続きロールバックでき、90日ごとに少なくとも1回同期すると、更新は以前と同様に増分されます。ただし、90日以上待機すると、アプリはデータベース全体を置き換えます。

この変更により、履歴テーブルのサイズがほぼ90%縮小されたため、履歴テーブルを維持すると、データベースは10倍ではなく2倍になります。このシステムのもう1つの利点は、必要に応じて履歴テーブルがなくても同期が機能することです。たとえば、一時的にオフラインにするメンテナンスを行う必要がある場合などです。または、異なる価格帯のアカウントに異なるロールバック期間を提供できます。また、ダウンロードする変更が90日を超える場合、通常、完全なファイルの方が増分形式よりも効率的です。

今日からやり直す場合、IDの競合チェックをスキップして、競合を排除するのに十分なキー長を目指し、念のため何らかのエラーチェックを行います。ただし、履歴テーブルと、最近の更新の増分ダウンロードまたは必要な場合の完全ダウンロードの組み合わせはうまく機能しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top