클라이언트-서버 동기화 패턴 / 알고리즘?
클라이언트-서버 동기화 패턴이 있어야한다고 생각합니다. 그러나 나는 완전히 하나를 구글에 실패했습니다.
상황은 매우 간단합니다. 서버는 여러 클라이언트가 동일한 데이터에 연결하고 조작하는 중앙 노드입니다. 충돌이 발생할 경우 서버에있는 모든 데이터가 우선 순위를 갖습니다 (사용자의 충돌 해결을 피하기 위해). 잠재적으로 많은 양의 데이터로 인해 부분 동기화가 선호됩니다.
그러한 상황에 대한 패턴 / 모범 사례가 있습니까, 아니면 모르는 경우-귀하의 접근법은 무엇입니까?
아래는 이제 내가 해결하려고 생각하는 방법입니다. 데이터와 평행하게 모든 트랜잭션 타임 스탬프가있는 수정 저널이 개최됩니다. 클라이언트가 연결되면 마지막 확인 이후 모든 변경 사항이 통합 된 형태로 수신됩니다 (서버는 목록을 살펴보고 삭제가 뒤 따르는 추가 사항을 제거하고 각 원자에 대한 업데이트를 병합하는 등). 짜잔, 우리는 최신 상태입니다.
대안은 각 레코드의 수정 날짜를 유지하고 데이터 삭제를 수행하는 대신 삭제 된 것으로 표시하는 것입니다.
이견있는 사람?
분산 변경 관리의 작동 방식을 살펴 봐야합니다. 델타 작업을 관리하는 SVN, CVS 및 기타 리포지토리를 살펴보십시오.
몇 가지 사용 사례가 있습니다.
변경 사항을 동기화하십시오. 변경 로그 (또는 델타 히스토리) 접근 방식이 적합합니다. 클라이언트는 델타를 서버로 보냅니다. 서버는 델타를 클라이언트에 통합하고 분배합니다. 이것이 일반적인 경우입니다. 데이터베이스는이를 "트랜잭션 복제"라고합니다.
클라이언트가 동기화를 잃었습니다. 백업 / 복원 또는 버그로 인해 발생합니다. 이 경우 클라이언트는 델타를 거치지 않고 서버에서 현재 상태를 가져와야합니다. 이것은 마스터에서 세부 사항까지의 사본이며 델타 및 성능이 저하됩니다. 일회성입니다. 클라이언트가 고장났습니다. 이를 최적화하지 말고 신뢰할 수있는 사본을 구현하십시오.
클라이언트가 의심 스럽다. 이 경우 클라이언트와 서버를 비교하여 클라이언트가 최신이고 델타가 필요한지 판별해야합니다.
변경 될 때마다 순차적으로 번호를 매기는 데이터베이스 (및 SVN) 디자인 패턴을 따라야합니다. 이렇게하면 클라이언트가 동기화를 시도하기 전에 사소한 요청 ( "어떤 수정본이 있어야합니까?")을 만들 수 있습니다. 그럼에도 불구하고 쿼리 ( "2149 이후의 모든 델타")는 클라이언트와 서버가 처리하기 매우 간단합니다.
팀의 일원으로 데이터 동기화와 관련된 많은 프로젝트를 수행 했으므로이 질문에 대답 할 수 있어야합니다.
데이터 동기화는 매우 광범위한 개념이므로 논의 할 방법이 너무 많습니다. 여기에는 장점과 단점이있는 다양한 접근 방식이 포함됩니다. 다음은 동기 / 비동기, 클라이언트 / 서버 / 피어 투 피어라는 두 가지 관점에 따라 가능한 분류 중 하나입니다. 동기화 구현은 이러한 요소, 데이터 모델 복잡성, 전송 및 저장되는 데이터 양 및 기타 요구 사항에 크게 좌우됩니다. 따라서 각 특정 경우에 앱 요구 사항을 충족하는 가장 간단한 구현을 선택해야합니다.
기존의 상용 솔루션을 검토하여 동기화 대상 객체의 세분성이 다른 몇 가지 주요 동기화 클래스를 설명 할 수 있습니다.
- 전체 문서 또는 데이터베이스의 동기화는 Dropbox, Google Drive 또는 Yandex.Disk와 같은 클라우드 기반 응용 프로그램에서 사용됩니다. 사용자가 파일을 편집하고 저장하면 새 파일 버전이 클라우드에 완전히 업로드되어 이전 사본을 덮어 씁니다. 충돌이 발생하면 두 파일 버전이 모두 저장되므로 사용자가 관련성이 높은 버전을 선택할 수 있습니다.
- 키-값 쌍의 동기화는 간단한 데이터 구조를 가진 앱에서 사용할 수 있습니다. 여기서 변수는 원자적인 것으로 간주됩니다 (즉, 논리 구성 요소로 나뉘 지 않음). 이 옵션은 값과 문서를 완전히 덮어 쓸 수 있으므로 전체 문서를 동기화하는 것과 유사합니다. 그러나 사용자 관점에서 문서는 여러 부분으로 구성된 복잡한 개체이지만 키-값 쌍은 짧은 문자열 또는 숫자입니다. 따라서이 경우 마지막으로 변경 한 경우 더 관련성 높은 값을 고려하여보다 간단한 갈등 해결 전략을 사용할 수 있습니다.
- 트리 또는 그래프로 구조화 된 데이터 동기화는 매번 업데이트 할 때마다 데이터베이스를 전체적으로 전송할 수있는 데이터 양이 큰보다 복잡한 응용 프로그램에서 사용됩니다. 이 경우 개별 개체, 필드 또는 관계 수준에서 충돌을 해결해야합니다. 우리는 주로이 옵션에 중점을 둡니다.
따라서이 기사에 대한 지식을 습득하여 핵심 데이터 기반 iOS 앱의 데이터 => 데이터 동기화 ( http://blog.denivip.ru/index.php/2014/04 주제에 관심이있는 모든 사람들에게 매우 유용 할 것으로 생각합니다. / data-syncing-in-core-data-based-ios-apps /? lang = en )
실제로 필요한 것은 OT ( Operational Transform )입니다. 이것은 많은 경우에 갈등을 수용 할 수도 있습니다.
이것은 여전히 활발한 연구 분야이지만 다양한 OT 알고리즘이 구현되어 있습니다. 나는 수년 동안 그러한 연구에 참여해 왔으므로이 경로가 당신에게 관심이 있는지 알려 주시면 관련 자료에 기꺼이 도와 드리겠습니다.
문제는 분명하지 않지만 내가 당신이라면 낙관적 잠금을 조사 할 것입니다. 서버가 각 레코드에 대해 리턴하는 시퀀스 번호로 구현 될 수 있습니다. 클라이언트가 레코드를 다시 저장하려고하면 서버에서받은 시퀀스 번호가 포함됩니다. 업데이트를받을 때 시퀀스 번호가 데이터베이스에있는 것과 일치하면 업데이트가 허용되고 시퀀스 번호가 증가합니다. 시퀀스 번호가 일치하지 않으면 업데이트가 허용되지 않습니다.
약 8 년 전에 앱용으로 이와 같은 시스템을 구축했으며 앱 사용이 증가함에 따라 발전한 몇 가지 방법을 공유 할 수 있습니다.
모든 장치의 모든 변경 (삽입, 업데이트 또는 삭제)을 "기록"테이블에 기록하여 시작했습니다. 예를 들어 누군가가 "contact"테이블에서 전화 번호를 변경하면 시스템은 contact.phone 필드를 편집하고 action = update, field = phone, record = [contact ID], value = [새 전화 번호]. 그런 다음 장치가 동기화 될 때마다 마지막 동기화 이후 기록 항목을 다운로드하여 로컬 데이터베이스에 적용합니다. 위에서 설명한 "트랜잭션 복제"패턴처럼 들립니다.
한 가지 문제는 다른 장치에서 항목을 만들 수있을 때 ID를 고유하게 유지하는 것입니다. 나는 이것을 시작할 때 UUID에 대해 몰랐기 때문에 자동 증가 ID를 사용하고 중앙 서버에서 실행되는 복잡한 코드를 작성하여 장치에서 업로드 된 새로운 ID를 확인하고 충돌이 발생하면 고유 ID로 변경합니다. 소스 장치가 로컬 데이터베이스에서 ID를 변경하도록 지시하십시오. 새 레코드의 ID를 변경하는 것만 큼 나쁘지는 않지만 연락처 테이블에 새 항목을 만든 다음 이벤트 테이블에 새 관련 항목을 만들면 외래 키도 있습니다. 확인하고 업데이트하십시오.
결국 UUID가 이것을 피할 수 있다는 것을 알았지 만 그때까지 내 데이터베이스가 상당히 커지고 전체 UUID 구현으로 인해 성능 문제가 발생할 것을 두려워했습니다. 따라서 전체 UUID를 사용하는 대신 무작위로 생성 된 8 자의 영숫자 키를 ID로 사용하기 시작했으며 충돌을 처리하기 위해 기존 코드를 그대로 두었습니다. 내 현재 8 문자 키와 UUID의 36 문자 사이에 불필요한 부풀림없이 충돌을 제거 할 수있는 스위트 스팟이 있어야하지만 이미 충돌 해결 코드가 있으므로 실험 해 보는 것이 우선 순위가 아닙니다. .
다음 문제는 히스토리 테이블이 나머지 데이터베이스 전체보다 약 10 배 크다는 것입니다. 이로 인해 스토리지가 비싸고 히스토리 테이블의 유지 보수가 어려울 수 있습니다. 이 전체 테이블을 유지하면 사용자가 이전 변경 사항을 롤백 할 수 있지만 과도하게 느껴지기 시작했습니다. 따라서 장치를 마지막으로 다운로드 한 기록 항목이 기록 테이블에 더 이상 존재하지 않으면 서버가 최근 기록 항목을 제공하지 않고 대신 모든 데이터를 포함하는 파일을 제공하는 루틴을 동기화 프로세스에 추가했습니다. 그 계정. 그런 다음 90 일보다 오래된 기록 항목을 삭제하기 위해 cronjob을 추가했습니다. 즉, 사용자는 90 일 미만의 변경 사항을 계속 롤백 할 수 있으며 90 일마다 한 번 이상 동기화하면 업데이트가 이전과 같이 증분됩니다. 하지만 90 일 이상을 기다리면
이 변경으로 인해 히스토리 테이블의 크기가 거의 90 % 줄었습니다. 이제 히스토리 테이블을 유지 보수하면 데이터베이스가 10 배가 아닌 2 배만 커집니다. 이 시스템의 또 다른 이점은 필요한 경우 기록 테이블 없이도 동기화를 계속 수행 할 수 있다는 것입니다. 또는 다른 가격대의 계정에 대해 다른 롤백 기간을 제공 할 수 있습니다. 다운로드 할 때까지 90 일이 지난 후에도 전체 파일이 증분 형식보다 효율적입니다.
오늘 다시 시작한 경우 ID 충돌 검사를 건너 뛰고 경우에 따라 일종의 오류 검사와 함께 충돌을 제거하기에 충분한 키 길이를 목표로합니다. 그러나 히스토리 테이블과 최근 업데이트를위한 증분 다운로드 또는 필요한 경우 전체 다운로드의 조합이 제대로 작동했습니다.
델타 (변경) 동기화를 들어, 당신은 다시 모든 구독 클라이언트에 대한 변경 사항을 게시 할 pubsub 패턴을 사용할 수 있습니다, 같은 서비스 푸셔는 이 작업을 수행 할 수 있습니다.
데이터베이스 미러의 경우 일부 웹 프레임 워크는 로컬 미니 데이터베이스를 사용하여 서버 측 데이터베이스를 브라우저 데이터베이스의 로컬에 동기화합니다. 부분 동기화가 지원됩니다. 계량기를 점검하십시오 .
참고 URL : https://stackoverflow.com/questions/413086/client-server-synchronization-pattern-algorithm
'IT story' 카테고리의 다른 글
JavaScript 신호음을 어떻게합니까? (0) | 2020.04.26 |
---|---|
PHP에서 사용자를위한 CSV 파일 생성 (0) | 2020.04.26 |
Swift 배열 할당이 일치하지 않는 이유가 있습니까 (참조 또는 딥 카피)? (0) | 2020.04.26 |
.NET의 API 주요 변경 사항에 대한 결정적인 가이드 (0) | 2020.04.26 |
객체의 메소드와 속성의 전체 목록을 얻는 방법? (0) | 2020.04.26 |