카우치베이스 모바일은 충돌을 처리하기 위해 다중 버전 동시성 제어(MVCC) 기술을 사용합니다. MVCC 기반 시스템의 문제점 중 하나는 시간이 지남에 따라 하나의 문서에 여러 개의 수정본이 생길 수 있다는 것입니다. 문서의 모든 수정본을 무기한 보관할 경우 데이터베이스가 매우 커질 수 있다는 결론을 내릴 수 있습니다. 이는 바람직하지 않습니다.
이번 글은 카우치베이스 모바일의 충돌 해결에 대한 시리즈의 두 번째 글입니다. 첫 번째 게시물에서는 갈등 해결의 이해에서 MVCC를 사용하여 Couchbase Mobile에서 문서 수정 및 충돌이 어떻게 처리되는지 그 비하인드 스토리를 살펴봤습니다. 이 글에서는 문서 리비전 트리의 크기를 관리하기 위해 Couchbase Mobile에서 사용되는 기술과 이와 관련된 애플리케이션의 역할에 대해 설명합니다.
배경
카우치베이스 모바일 스택에는 다음이 포함됩니다. 카우치베이스 라이트 장치에서 로컬로 실행되는 임베디드 데이터베이스와 동기화 게이트웨이 클라우드에서 일반적으로 지원되는 카우치베이스 서버 클라우드에서 데이터를 유지합니다. 동기화 게이트웨이는 여러 장치에 걸친 문서 복제를 처리합니다. 하나의 문서를 여러 장치에서 동시에 업데이트할 수 있습니다.
카우치베이스 모바일의 문서는 문서 ID, 현재 수정본 ID, JSON 본문 및 메타데이터로 구성됩니다. 메타데이터는 무엇보다도 문서의 수정본 기록을 보관합니다. 현재 프로덕션 버전인 Couchbase Mobile에서 메타데이터는 문서에 포함된 특수 _sync 속성에 저장됩니다. In 동기화 게이트웨이 V1.5를 클릭하면 메타데이터가 문서에서 XATTR로 이동합니다.
이 게시물은 Couchbase Mobile의 문서 리비전 트리 구조와 현재 리비전의 개념을 잘 알고 있다고 가정합니다. 더 자세히 알고 싶으시면 다음 게시물을 참조하세요. 갈등 해결의 이해.
데이터베이스 크기 관리 기술
문서가 너무 커지는 것을 방지하기 위해 Couchbase Mobile은 다음과 같은 세 가지 기술을 사용합니다,
- 압축
- 가지 치기
- 문서 만료
동기화 게이트웨이와 카우치베이스 라이트는 정리 프로세스를 약간 다르게 처리합니다. 해당되는 경우 해당 게시물에 차이점이 명시되어 있습니다.
압축
압축은 다음의 JSON 본문을 퍼지하는 프로세스로 정의됩니다. 비잎 수정본. 잎 수정본은 압축 중에 제거되지 않습니다.
동기화 게이트웨이 켜기
동기화 게이트웨이에서 압축은 시스템에서 백그라운드에서 주기적으로 실행됩니다. 또한 애플리케이션은 압축 프로세스를 수동으로 호출할 수 있습니다. 관리자 인터페이스의 컴팩트 API
카우치베이스 라이트에서
카우치베이스 라이트에서는 압축을 수동으로만 호출할 수 있습니다. 컴팩트 API CBLDatabase 개체에서
충돌 해결이 압축에 미치는 영향
압축 프로세스는 리프 노드의 JSON 본문을 제거하지 않습니다. 따라서 해결되지 않은 충돌하는 브랜치가 많으면 JSON 본문이 있는 리프 노드가 많이 남게 됩니다.
- 사례 1: 충돌이 해결되지 않으면 컴팩션은 모든 리프 노드의 JSON 본문을 유지합니다.

- 사례 2: 충돌이 해결되면(즉, 비승리 브랜치가 툼스톤 처리되면), 압축은 리프 노드가 아닌 JSON 본문을 제거합니다.

따라서 충돌을 해결하여 오래되고 사용하지 않는 잎 개정판을 모두 정리하는 것이 중요합니다.
가지 치기
가지치기는 오래된 메타데이터 및/또는 JSON 본문과 관련된 메타데이터 및/또는 JSON 본문을 삭제하는 프로세스입니다. 비잎 수정. 리프 리비전은 영향을 받지 않습니다. 이 프로세스는 리비전이 추가될 때마다 자동으로 실행됩니다. 기본적으로 동일하지만, 가지치기 알고리즘은 동기화 게이트웨이와 Couchbase Lite에서 약간 다르게 작동합니다.

동기화 게이트웨이 켜기
"이전 수정본"은 다음과 같이 지정된 값보다 오래된 수정본입니다. revs_limit 데이터베이스 구성 속성을 설정합니다. revs_limit 속성의 기본값은 1000이며, 이는 지난 1000개의 수정본에 해당하는 메타데이터가 동기화 게이트웨이에 저장된다는 의미입니다. 가지치기 프로세스가 오래된 리비전의 JSON 본문을 즉시 제거하지는 않지만, 기본 TTL 값인 5분보다 오래된 문서의 모든 리프가 아닌 리비전의 JSON 본문은 주기적으로 실행되는 백그라운드 프로세스에 의해 자동으로 정리됩니다.
알고리즘
- 최소 생성 수 찾기 gmin(첫 번째 구성 요소는 리비전 ID)를 사용하여 모든 리프 리비전의 리비전을 표시합니다.
- 생성 번호 g가 ≤인 모든 비리프 리비전을 삭제합니다. gmin -
revs_limit
충돌이 있는 게이트웨이 가지 치기 동기화 : 예제
이 예제에서는
- 다음과 같이 가정합니다.
revs_limit
구성이 다음과 같이 설정되어 있습니다. 2 (예시용으로만 제공됨) - 문서에 3세대에서 해결되지 않은 상충되는 수정본이 있습니다.

카우치베이스 라이트에서
"이전 수정본"은 다음에서 지정한 값보다 오래된 수정본입니다. 최대 레브 트리 깊이 속성을 설정할 수 있습니다. maxRevTreeDepth 값의 기본값은 20이며, 이는 다음을 의미합니다. 메타데이터 및 JSON 본문 지난 20개 개정판에 해당하는 항목은 Couchbase Lite에 유지됩니다.
기본적으로 이전 리비전의 JSON 본문을 임시 백업(TTL 5분)하는 동기화 게이트웨이와 달리, Couchbase Lite의 가지치기 프로세스는 메타데이터는 물론 오래된 비리비전의 JSON 본문도 제거합니다.
다양한 Couchbase Lite 플랫폼에서 가지치기 알고리즘이 처리되는 방식에 약간의 차이가 있을 수 있다는 점에 유의해야 합니다. 사용자의 관점에서 보면, Couchbase Lite의 가지치기 기술은 이전 개정판의 메타데이터와 JSON 본문을 최대 레브 트리 깊이
값입니다.
알고리즘
- 트리에서 무덤이 없는 각 분기에 대해 세대 Id, g < (분기의 깊이 -) 인 수정본을 잘라냅니다.
최대 레브 트리 깊이
)
가지치기 후 문서는 다음과 같이 끝날 수 있습니다. 연결이 끊긴 분기. 리비전 트리가 손상된 상태가 아니며 승리한 리비전을 선택하는 논리가 여전히 적용됩니다. 그러나 충돌을 해결하기 위해 특정 병합을 수행하지 못할 수 있으므로 문제가 되는 경우에는 피해야 합니다.
충돌이 있는 카우치베이스 라이트 가지치기 : 예제
이 예제에서는
- 다음과 같이 가정합니다.
최대 레브 트리 깊이
구성이 다음과 같이 설정되어 있습니다. 2 (다시 말하지만, 실제로는 절대 하고 싶지 않을 것입니다.) - 문서에 3세대에서 해결되지 않은 상충되는 수정본이 있습니다.

갈등 해결이 가지 치기에 미치는 영향
- 가지치기 프로세스는 잎 수정본을 잘라내지 않습니다. 따라서 해결되지 않은 충돌하는 가지가 많으면 많은 수의 잎 노드가 남게 됩니다.
- 동기화 게이트웨이에서 가지치기 알고리즘은 리비전 트리에서 가장 짧고 툼스톤이 없는 브랜치에 적용됩니다. 즉, 해결되지 않은 충돌 브랜치가 많은 경우 가지치기가 이전 리비전 중 일부를 삭제하지 못할 수 있으며, 다음 예를 고려하세요,
- 시나리오 1 : 충돌이 해결되지 않은 경우, 가장 짧은 브랜치가 충돌하는 브랜치일 수 있으므로 가지치기를 해도 오래된 수정본이 모두 제거되지 않을 수 있습니다.
-
- 시나리오 2 : 그러나 충돌이 해결된 경우, gmin 는 이긴 리비전 브랜치의 리프 노드에 해당합니다.
- 동기화 게이트웨이에서 충돌이 해결되지 않은 경우 충돌하는 리비전의 부모 노드가 조기에 제거될 수도 있습니다. 이렇게 되면 앞서 설명한 대로 연결이 끊어진 브랜치 상태가 됩니다.
문서 만료
문서가 만료되면 문서의 모든 수정본을 포함한 모든 흔적이 시스템에서 제거됩니다. 사용자는 문서 만료 시기를 제어할 수 있습니다. 문서가 조기에 만료될 수 있으므로 사용자는 문서의 만료 값을 변경할 때 주의해야 합니다. 이 기능은 짧은 기간 동안만 필요할 수 있는 임시 문서를 만들 때 유용합니다.
동기화 게이트웨이 켜기
다음을 통해 동기화 게이트웨이에 문서를 작성하는 경우 PUT 문서 또는 bulk_docs API를 통해 사용자는 __exp
속성을 문서 본문에 추가하여 문서 만료 시점을 지정할 수 있습니다.
exp 값에 지원되는 형식은 다음과 같습니다:
- JSON 번호. 30일 미만인 경우 TTL(초), 30일 이상인 경우 유닉스 시간
- JSON 문자열(숫자 형식) - JSON 번호와 동일합니다.
- JSON 문자열(ISO-8601 날짜)
- JSON null. 만료를 0으로 설정합니다(만료 없음).
카우치베이스 라이트에서
그리고 만료일 속성을 사용하여 문서가 만료되어야 하는 시기를 지정할 수 있습니다. 만료 날짜를 수동으로 지정하면 동기화 게이트웨이와 동기화할 기회를 갖기 전에 오프라인 모드에서 Couchbase Lite에 추가된 문서가 만료될 위험이 있다는 점에 유의하세요.
리비전 트리의 최대 깊이 구성
가지치기에 대한 섹션에서 설명한 것처럼, 가지치기에 대한 섹션에서 설명한 것처럼 최대 레브 트리 깊이
속성의 기본값은 20이고, 카우치베이스 라이트 데이터베이스의 revs_limits
속성의 기본값은 1000입니다.
이 값은 가지치기 프로세스에서 메타데이터가 살아남는 수정본의 수에 영향을 줍니다. 따라서 값이 매우 크면 문서 메타데이터 기록이 매우 커져 데이터베이스 스토리지 요구량이 증가할 수 있음을 의미합니다.
공간을 절약하기 위해 이러한 값을 줄이고 싶은 유혹을 받을 수 있습니다. 하지만 아래에서 설명하는 것처럼 매우 작게 만들면 바람직하지 않은 결과를 초래할 수 있습니다.
- 충돌하는 브랜치의 부모 노드는 충돌이 해결되기 전에 가지치기를 당하여 고아가 된 리프 노드가 될 수 있습니다. 애플리케이션이 동시 변경 사항을 n-방향으로 병합하려는 경우 이는 바람직하지 않을 수 있습니다. 이 상태가 되면 충돌을 해결하는 유일한 옵션은 이기는 분기를 선택하고 이기지 못한 충돌하는 모든 분기를 묘비명하는 것입니다.
- 다음과 같은 결과가 나올 수 있습니다. 연결이 끊어진 분기 를 추가합니다. 연결이 끊어진 브랜치는 공통 조상이 없는 브랜치입니다. 그 자체로는 큰 문제가 되지 않을 수 있지만, 애플리케이션이 비연결 브랜치를 무덤으로 만드는 역할을 합니다.
아래 예시에서 동기화 후 장치는 공통 조상이 없는 두 개의 연결이 끊긴 분기 [16..19]와 [35..38]로 끝납니다.

위의 시나리오는 기본 트리 깊이 속성 값으로도 발생할 수 있습니다. 그러나 값을 너무 낮게 설정하면 이 상태가 발생할 가능성이 크게 높아집니다.
다음 단계
MVCC 기반 시스템에서 중요한 고려 사항 중 하나는 리비전 트리의 크기를 관리하고 부풀어 오르는 것을 방지하는 것입니다. 이 게시물에서는 문서 크기를 제어하기 위해 Couchbase Mobile에서 사용할 수 있는 기술과 충돌 해결이 데이터베이스 크기에 미치는 영향에 대해 설명했습니다.
질문이나 피드백이 있으시면 아래에 댓글을 남기거나 트위터 @rajagp 또는 이메일로 저에게 연락해 주세요. priya.rajagopal@couchbase.com. . 카우치베이스 포럼 를 통해 질문할 수 있습니다.
마지막으로 트라운 레이든에게 감사의 인사를 전합니다. Traun@couchbase.com 의 심도 있는 검토를 위해 Sync 게이트웨이 팀과 Jens Alfke jens@couchbase.com 그리고 짐 보든 jim.borden@couchbase.com Couchbase Lite 팀에게 의견을 구했습니다.