Development Tip

클라이언트-서버 데이터베이스 동기화

yourdevel 2020. 10. 12. 08:14
반응형

클라이언트-서버 데이터베이스 동기화


항상 온라인 상태가 아닌 클라이언트 응용 프로그램과 중앙 서버의 데이터를 동기화하기위한 몇 가지 일반적인 전략을 찾고 있습니다.

내 특별한 경우에는 sqlite 데이터베이스가있는 안드로이드 폰 애플리케이션과 MySQL 데이터베이스가있는 PHP 웹 애플리케이션이 있습니다.

사용자는 전화 애플리케이션과 웹 애플리케이션에서 정보를 추가하고 편집 할 수 있습니다. 전화가 서버와 즉시 통신 할 수없는 경우에도 한 곳에서 변경 한 내용이 모든 곳에 반영되도록해야합니다.

전화에서 서버로 또는 그 반대로 데이터를 전송하는 방법에 대해서는 관심이 없습니다. 예를 들어 MySQL에서 사용할 수있는 복제 기능을 사용할 수 없기 때문에 내 특정 기술에 대해서만 언급합니다.

클라이언트-서버 데이터 동기화 문제가 오랫동안 존재 해 왔음을 알고 있으며 문제를 처리하기위한 패턴에 대한 정보 (기사, 서적, 조언 등)를 원합니다. 강점, 약점 및 장단점을 비교하기 위해 동기화를 처리하는 일반적인 전략에 대해 알고 싶습니다.


가장 먼저 결정해야 할 것은 변경 사항이 충돌하는 경우 어느 쪽이 "권한"으로 간주되는지에 대한 일반적인 정책입니다.

즉, 레코드 # 125가 1 월 5 일 오후 10시에 서버에서 변경되고 동일한 레코드가 1 월 5 일 오후 11시에 전화기 중 하나 (클라이언트 A라고 부릅니다)에서 변경되었다고 가정합니다. 마지막 동기화는 1 월 3 일이었습니다. 그런 다음 사용자는 1 월 8 일에 다시 연결합니다.

변경해야 할 항목을 식별하는 것은 클라이언트와 서버가 모두 마지막 동기화 날짜를 알고 있으므로 마지막 동기화 이후에 생성되거나 업데이트 된 모든 항목 (아래 참조)을 조정해야 한다는 점에서 "쉽습니다" .

따라서 변경된 유일한 레코드가 # 125라고 가정합니다. 둘 중 하나가 자동으로 "승리"하고 다른 버전을 덮어 쓰도록 결정하거나 사용자가 올바른 버전 (서버 또는 클라이언트)을 결정하고 다른 버전을 덮어 쓸 수있는 조정 단계를 지원해야합니다.

이 결정은 매우 중요하며 클라이언트의 "역할"에 가중치를 두어야합니다. 특히 클라이언트와 서버 사이에 잠재적 충돌이있을 때뿐만 아니라 다른 클라이언트가 동일한 레코드를 변경할 수있는 경우에 더욱 그렇습니다.

[# 125가 두 번째 클라이언트 (클라이언트 B)에 의해 수정 될 수 있다고 가정하면 아직 동기화되지 않은 클라이언트 B가 동일한 레코드의 또 다른 버전을 제공하여 이전 충돌 해결에 대한 의구심을 갖게 될 가능성이 있습니다.]

위의 " 생성 또는 업데이트 된 "지점 과 관련하여 ... 레코드가 클라이언트 중 하나에서 생성 된 경우 레코드를 올바르게 식별 할 수있는 방법은 무엇입니까 (문제 도메인에서 이것이 의미가 있다고 가정)? 앱이 비즈니스 연락처 목록을 관리한다고 가정 해 보겠습니다. 클라이언트 A가 새로 생성 된 John Smith를 추가해야한다고 말하고 서버에 클라이언트 D가 어제 생성 한 John Smith가있는 경우 ... 두 레코드가 서로 다른 사람이 아님을 확신 할 수 없기 때문에 생성합니까? 사용자에게도이 충돌을 조정하도록 요청 하시겠습니까?

클라이언트가 데이터 하위 집합의 "소유권"을 가지고 있습니까? 즉, 클라이언트 B가 영역 # 5의 데이터에 대한 "권한"으로 설정된 경우 클라이언트 A가 영역 # 5의 레코드를 수정 / 생성 할 수 있습니까? (이렇게하면 갈등 해결이 더 쉬워 지지만 상황에 따라 실행 불가능할 수 있습니다).

요약하자면 주요 문제는 다음과 같습니다.

  • 분리 된 클라이언트가 새 레코드를 만들기 전에 서버에 액세스하지 않았을 수 있음을 고려하여 "ID"를 정의하는 방법입니다.
  • 이전 상황은 솔루션이 아무리 정교하더라도 데이터 중복을 초래할 수 있으므로 이러한 문제를 정기적으로 해결하는 방법과 고객에게 "레코드 # 675"로 간주 한 내용이 실제로 병합 / 대체되었음을 클라이언트에게 알리는 방법을 예측해야합니다. 기록 # 543
  • 충돌을 법정 화폐 로 해결할지 (예 : "마지막 동기화 이후에 전자가 업데이트 된 경우 서버 버전이 항상 클라이언트보다 우선합니다") 또는 수동 개입 으로 해결할지 결정합니다.
  • fiat의 경우 , 특히 클라이언트가 우선권을 갖는다 고 결정하는 경우, 더 많은 변경 사항이있을 수있는 아직 동기화되지 않은 다른 클라이언트를 처리하는 방법도주의해야합니다.
  • 이전 항목은 데이터의 세분성을 고려하지 않았습니다 (설명을 더 간단하게 만들기 위해). 내 예에서와 같이 "기록"수준에서 추론하는 대신 필드 수준에서 변경 내용을 기록하는 것이 더 적절할 수 있습니다. 또는 한 번에 일련의 레코드 (예 : 개인 레코드 + 주소 레코드 + 연락처 레코드)를 작업하여 집계를 일종의 "메타 레코드"로 취급합니다.

서지:

(마지막 세 개는 ACM 디지털 라이브러리에서 가져온 것으로 회원인지 다른 채널을 통해 얻을 수 있는지 알 수 없습니다.)

로부터 Dr.Dobbs의 사이트 :

  • SQL Server CE 및 SQL RDA로 앱 만들기 by Bill Wagner 2004 년 5 월 19 일 (데스크톱 및 모바일 PC 용 애플리케이션 설계 모범 사례-Windows / .NET)

arxiv.org에서 :

  • 충돌없는 복제 된 JSON 데이터 유형 -이 문서는 JSON CRDT 구현을 설명합니다 (충돌없는 복제 된 데이터 유형-CRDT는 동시 수정을 지원하고 이러한 동시 업데이트의 수렴을 보장하는 데이터 구조 제품군입니다).

모든 테이블에 타임 스탬프이 있고 삽입하거나 업데이트 할 때마다 영향을받는 각 행의 타임 스탬프 값을 업데이트하는 것이 좋습니다 . 그런 다음 타임 스탬프가 대상 데이터베이스에있는 것보다 최신인지 확인하는 모든 테이블을 반복합니다. 더 새로운 경우 삽입 또는 업데이트해야하는지 확인하십시오.

관찰 1 : 행이 소스 db에서 삭제되고 서버 db에서 동일한 작업을 수행해야하므로 물리적 삭제에 유의하십시오. 이 문제를 해결하면 물리적 삭제를 피하거나 타임 스탬프가있는 테이블의 모든 삭제를 로깅 할 수 있습니다. 다음과 같습니다. DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp)따라서 DeletedRows 테이블의 모든 새 행을 읽고 table_name, pk_column 및 pk_column_value를 사용하여 서버에서 삭제를 실행해야합니다.

관찰 2 : 다른 테이블과 관련된 테이블에 데이터를 삽입하면 실패 할 수 있으므로 FK에 유의하십시오. 데이터 동기화 전에 모든 FK를 비활성화해야합니다.


누군가 비슷한 디자인 문제를 다루고 있고 여러 Android 장치에서 변경 사항을 동기화해야하는 경우 Android 용 Google 클라우드 메시징 (GCM) 확인하는 것이 좋습니다 .

한 클라이언트에서 수행 한 변경 사항을 다른 클라이언트로 전파해야하는 하나의 솔루션을 개발 중입니다. 그리고 방금 개념 증명 구현 (서버 및 클라이언트)을 구현했으며 매력처럼 작동합니다.

기본적으로 각 클라이언트는 델타 변경 사항을 서버로 보냅니다. 예 : 리소스 ID ABCD1234가 값 100에서 99로 변경되었습니다.

Server validates these delta changes against its database and either approves the change (client is in sync) and updates its database or rejects the change (client is out of sync).

If the change is approved by the server, server then notifies other clients (excluding the one who sent the delta change) via GCM and sends multicast message carrying the same delta change. Clients process this message and updates their database.

Cool thing is that these changes are propagated almost instantaneously!!! if those devices are online. And I do not need to implement any polling mechanism on those clients.

Keep in mind that if a device is offline too long and there is more than 100 messages waiting in GCM queue for delivery, GCM will discard those message and will send a special message when the devices gets back online. In that case the client must do a full sync with server.

Check also this tutorial to get started with CGM client implementation.


this answers developers who are using the Xamarin framework (see https://stackoverflow.com/questions/40156342/sync-online-offline-data)

A very simple way to achieve this with the xamarin framework is to use the Azure’s Offline Data Sync as it allows to push and pull data from the server on demand. Read operations are done locally, and write operations are pushed on demand; If the network connection breaks, the write operations are queued until the connection is restored, then executed.

The implementation is rather simple:

1) create a Mobile app in azure portal (you can try it for free here https://tryappservice.azure.com/)

2) connect your client to the mobile app. https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

3) the code to setup your local repository:

const string path = "localrepository.db";

//Create our azure mobile app client
this.MobileService = new MobileServiceClient("the api address as setup on Mobile app services in azure");

//setup our local sqlite store and initialize a table
var repository = new MobileServiceSQLiteStore(path);

// initialize a Foo table
store.DefineTable<Foo>();

// init repository synchronisation
await this.MobileService.SyncContext.InitializeAsync(repository);
var fooTable = this.MobileService.GetSyncTable<Foo>();

4) then to push and pull your data to ensure we have the latest changes:

await this.MobileService.SyncContext.PushAsync();
await this.saleItemsTable.PullAsync("allFoos", fooTable.CreateQuery());

https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started-offline-data/


I suggest you also take a look at Symmetricds. it is a SQLite replication library available to android systems. you can use it to synchronize your client and server database, I also suggest to have separate databases on server for each client. Trying to hold the data of all users in one mysql database is not always the best idea. Specially if the user data is going to grow fast.

참고URL : https://stackoverflow.com/questions/3406891/synchronizing-client-server-databases

반응형