생성 식별자

bsr은 복제 데이타 생성을 식별하기 위해 생성 식별자(GI, Generation Identifiers)를 사용합니다. 이것은 bsr 내부 메카니즘에서 아래와 같은 용도로 사용됩니다.

  • 두 노드가 실제 클러스터의 멤버인지 결정할 때 (같은 클러스터 내의 노드가 아닌 우연한 연결에 대한 식별)

  • 노드 간 백그라운드 재동기화의 방향을 결정할 때

  • 전체 재동기화가 필요한지 혹은 부분 재동기화로 충분한지 결정할 때

  • 스플릿 브레인(이하 SB)을 식별할 때

생성 식별자

bsr은 다음의 경우에 새로운 데이터 생성(Data Generation)이 시작된 것으로 간주하고 새로운 GI 를 생성합니다.

  • 초기 전체 동기화 시

  • disconnected 된 리소스가 Primary 역할로 승격할 때

  • Primary 역할의 리소스가 disconnecting 될 때

    • 새로운 GI 가 생성되는 시점은 디스크에 쓰기 I/O 가 발생하여 실제 데이터가 변경될 때 입니다.

따라서, 리소스가 Connected 연결 상태에 있고 양 노드의 디스크 상태가 UpToDate 이면 양 노드의 현재 GI는 동일하다 라고 할 수 있습니다. 반대의 경우도 마찬가지입니다.
모든 새로운 데이터 생성은 8 바이트의 UUID(universally unique identifier) 로 식별합니다. UUID의 최하위 비트는 노드의 역할을 표현하며 Primary는 1, Secondary는 0으로 설정됩니다. 

GI 튜플

bsr은 로컬 리소스 메타 데이타 내에 현재와 과거의 데이터 생성(data generation) 정보를 기본적으로 4개(Tuple)로 관리합니다.

  • Current UUID - 로컬노드의 현재 data generation에 대한 GI(생성 식별자)입니다. 리소스가 Connected 상태이고 동기화가 된 상태라면 이 Current UUID 는 양 노드 동일합니다.

  • Bitmap UUID - 디스크상의 동기화 비트맵의 변화를 추적하는 UUID입니다. 디스크의 동기화 비트맵 자체를 보면, 이 식별자는 disconnected 모드 상태에서만 관련이 있습니다. 만일 리소스가 Connected 라면 이 UUID는 항상 비어(zero)있게 됩니다.

  • Two Historical UUIDs - 현재의 Current UUID의 이전의 상태였던 data generation 식별자들이며 2개를 기억하고 있습니다. 

이 4가지 모두를 묶어서 "generation identifier tuple" 또는 짧게 "GI 튜플" 이라고 합니다.

GI 변경 과정

새로운 데이터 생성 시작

  • 노드간 연결이 끊어 질 때 (네트워크 오류, 수동조작 포함)

  • 연결된 상태에서 상대 노드의 디스크가 복제 데이터를 반영할 수 없는 상태 일 경우(peer-disk:Outdated) 

bsr은 위 두 가지 경우에 대해 로컬 GI를 다음과 같은 방법으로 수정합니다.

  1. 새로운 데이터 생성을 위해 신규 UUID를 생성합니다. 이 UUID는 Primary 노드를 위한 새로운 Current UUID가 됩니다. 

  2. 이전의 UUID는 이제 비트맵 변화 상황을 추적하는 generation을 의미하기 때문에, Primary 노드에 대한 새로운 Bitmap UUID가 됩니다.

  3. Secondary 노드에서는 GI 튜플의 변화가 없습니다.

UUID는 볼륨에 쓰기 I/O 가 발생 되었을 때 신규로 생성됩니다. 따라서 GI가 생성되는 보다 더 정확한 조건은 연결이 끊어지는 등의 기존 조건에 더해 볼륨의 쓰기 I/O 발생이 요구됩니다.

재동기화 시작

재동기화가 시작될 때 GI 튜플의 변화는 없습니다.

재동기화 완료

재동기화가 완료되면 동기화 소스는 비트맵 uuid 를 rotate 시키고 동기화 타겟은 동기화 소스의 GI 튜플 전체 셋을 수신하여 동일하게 반영합니다.

GI 상태 식별

노드간에 연결이 맺어지면 두 노드는 현재 사용할 수 있는 GI 를 교환하고, 거기에 맞춰서 적절한 동작을 진행하는데 여기엔 몇가지 동작이 존재합니다.

  • 양쪽의 Current UUID가 비어 있는 경우
    양쪽 Current UUID가 비어 있는 것으로 감지하였다면, 이런 경우는 보통 새롭게 리소스를 구성하고 동기화가 시작된 적이 없는 상황입니다. 여기서는 동기화가 자동으로 진행되지 않으며 수동으로 동기화를 시작해주어야 합니다.

  • 한쪽 노드의 Current UUID가 비어 있는 경우
    상대 노드의 Current UUID는 비어있고 자신의 것은 그렇지 않은 것을 감지하였다면, 이런 경우는 보통 새롭게 구성된 리소스에서 전체 동기화를 바로 시도한 상태이고, 로컬노드가 동기화의 소스로 선택된 경우입니다. bsr 내부적으로는 사용하고 있는 영역의 모든 비트를 on-disk sync bitmap에 설정하고 소스로써 동기화를 시작합니다. 반대의 경우는 (로컬 UUID가 비어있고, 상대가 비어있지 않을 때) bsr이 동일한 절차를 진행하겠지만 로컬 노드가 타겟으로 동기화 되는 것만 다릅니다.

  • 양쪽의 Current UUID가 동일한 경우
    자신의 Current UUID와 상대의 UUID가 비어있지 않고 같으면, 이런 경우는 보통 Secondary 역할 중 disconnected 모드가 되고 disconnected 중에 어떤 노드에서도 승격이 없었을 때 발생하는 경우입니다. 동기화가 필요하지 않은 상태이고 동기화가 진행되지도 않습니다.

  • Bitmap UUID가 상대 노드의 Current UUID와 일치하는 경우
    자신의 Bitmap UUID가 상대의 Current UUID와 같고 상대의 Bitmap UUID 가 비어있음을 감지하였다면, 이런 경우는 정상적인 상태이며 Secondary 역할일 때 장애 상황이 생겨서 Primary 역할로 승격시킨 경우입니다. 이것은 상대 노드는 Primary가 된 적이 없으며 그 전까지는 동일한 data generation으로 작업되었음을 의미합니다. bsr은 로컬노드를 동기화 소스로 설정하고 백그라운드 재동기화를 할 수 있도록 준�� 합니다.
    반대로 로컬노드가 자신의 Bitmap UUID는 비어있고 상대의 Bitmap이 자신의 Current UUID와 동일하다는 것을 인지한다면 이것도 정상적이며 로컬 노드의 실패 이후에 발생한 것입니다. bsr은 로컬노드를 동기화 타겟으로 놓고 백그라운드 재동기화를 준비합니다.

  • Current UUID가 상대 노드의 Historical UUID와 일치하는 경우
    자신의 Current UUID가 상대 노드의 Historical UUID와 일치하는 것을 감지하였다면, 이는 ��음과 같은 상황을 의미합니다. 2개의 데이타 셋(data sets)이 공통의 이전 세대 내용을 공유하는 동안, 상대 노드는 최신의 데이터를 가지지만 Bitmap 정보는 지난 시점의 것이기에 사용할 수 없다는 것을 의미합니다. 따라서 일반적인 동기화로는 충분하지 못할 수 있습니다. 이런 경우 bsr은 디바이스 전체를 out-of-sync 로 마킹을 하고 로컬 노드를 동기화 타겟이 되게하여 전체 백그라운드 재동기화를 시도합니다. 이와 반대로 로컬 노드의 Historical UUID 중에 상대의 Current UUID와 매칭되는 경우에는 로컬 노드를 동기화 소스가 되게하고 그 외에는 동일한 절차를 수행합니다.

  • Bitmap UUID는 일치, Current UUID는 불일치하는 경우
    자신의 Current UUID와 상대의 Current UUID와는 다르고 Bitmap UUID는 일치하는 것을 감지하였다면 스플릿 브레인(Split-brain)이 발생한 것입니다. 양 노드는 disconnect 상태로 남겨지고 자동해결이 설정되어 있지 않는 한 작업자가 직접 수동으로 스플릿 브레인 상황을 해결해야 합니다.

  • Current / Bitmap UUID 모두 불일치 하고 Historical UUID 가 일치하는 경우
    자신의 Current, Bitmap UUID가 각각의 상대 UUID와 다르고 Historical UUID 중 하나가 일치하는 것을 감지 하였다면 이전 조상 세대에서의 스플릿 브레인 상황입니다. 따라서 자동복구 설정이 되어있다 하더라도 의미가 없으며 수동으로 복구해야 합니다. BSR은 disconnect 상태가 되고 작업자가 직접 스플릿 브레인 상황을 해결해야 합니다.

  • 어떠한 UUID도 일치하지 않는 경우
    마지막으로, 두 노드의 GI 튜플에서 매칭되는 것이 한가지도 없다면 관련없는 데이타라고 경고를 남기고 disconnect 합니다. 이것은 전혀 관련 없는 노드간에 연결될 것을 대비한 안전조치입니다.