버전 스탬프

‘빅데이터 세상으로 떠나는 간결한 안내서 NoSQL’를 읽고 정리하고자함


요점 정리

  • 버전 스탬프는 동시성 충돌을 탐지하는데 도움이 됌
    • 데이터를 읽은 다음 업데이트할 때, 버전 스탬프를 확인해 그 사이 아무도 데이터를 업데이트하지 않았는지 확인할 수 있음
  • 버전 스탬프는 4가지 방법, 이 것들을 조합해서 구현할 수 있음
    1. 카운터
    2. GUID
    3. 콘텐츠 해시
    4. 타임스탬프
  • 분산시스템에서 버전 스탬프의 벡터를 사용하면 서로 다른 노드에서 쓰기 출돌이 일어났는지 탐지할 수 있음

  • NoSQL의 비판은 ‘트랜잭션 지원이 미비’ 함
    • 하지만, 집합 하나에 대해서는 원자적 업데이트를 지원함
  • 그러나, 트랜잭션에도 제약이 있는데, 트랜잭션 시스템에서도 여전히 사람의 개입이 필요하고, 트랜잭션 범위에 포함할 수 없는 업데이트도 처리해야함
    • 트랜잭션에 포함할 경우 트랜잭션을 너무 길게 열어 두어야함
  • 이런 경우, 버전 스탬프(version stamp)로 대처할 수 있

1. 업무 트랜잭션과 시스템 트랜잭션

  • 업무 트랙잭션
    • 사용자가 생각하는 트랙잭션
    • e.g) 제품 목록을 살펴보고 적당한 가격의 위스키 한 병을 고르고, 신용카드 정보 입력하고 주문을 승인하는 것
    • 하지만, 이 모든 과정이 데이터베이스에서 제공하는 시스템 트랜잭션에서 이루어지지 않음
    • 사용자가 신용카드를 찾으려다가 친구 전화받고 점심을 먹으러 나간 동안 데이터베이스 항목에 잠금을 설정해야하기 때문
  • 보통 애플리케이션은 사용자와 상호작용이 끝난 시점에 시스템 트랜잭션을 시작하므로, 잠금은 짧은 시간 동안만 설정
  • 그러나, 문제는 계산과 결정이 이미 변경된 데이터에 기반을 두고 이루어질 수 있다는 점..
    • e.g) 위스크 가격이 업데이트 되거나, 누군가 고객 주소를 업데이트하거나, 배송비가 변경되거나..
  • 이런 문제를 해결하는 기법은 ‘오프라인 동시성’
    • 조건적 업데이트의 한 형태인 낙관적 오프라인 잠금이 유용함
      • 트랙재션을 커밋하기 전에 트랜잭션에서 사용하는 정보가 처음 읽어 사용자에게 표시한 시점 이후로 변경되지 않았는지 다시 읽어 확인하는 방법
  • 이 방법은 다음과 같이 구현할 수 있음
  1. 데이터베이스 레코드의 데이터가 바뀔 때마다 바뀌는 레코드, 즉 버전 스탬프를 추가
    • 데이터를 읽을 때 버전 스탬프를 기록해두면 데이터 쓸 때 버전이 바꼈는지 확인할 수 있음
    • HTTP etag (entity tag) 방법도 유사
      • 리소스 요청할 때 마다 서버는 헤더에 etag를 넣어 응답하고, etag는 리소스의 버전을 나타내는 문자열
      • 리소스를 업데이트할 때 가장 최근 GET 요청에서 얻은 etag를 제공해 조건적 업데이트를 사용할 수 있음
      • 서버에서 리소스가 변경되었다면 etag는 다를 것이고, 서버는 업데이트를 거부하고 412(Precondition Failed)올
  2. 자원이 업데이트될 때 마다 항상 증가하는 카운터를 사용하는 것
    • 카운터는 어떤 저번이 다른 버전보다 나중인지 쉽게 확인 가능
    • 서버에서 카운터값이 중복되지 않도록 생성하려면 단일 마스터가 필요힘
  3. GUID (유일성을 보장되는 큰 난수)
    • GUID는 날짜, 하드웨어 정보, 기타 임의 정보를 조합해 샐ㅇ성
    • 누구나 생성할 수 있고 중복이 되지 않는 단점이 있지만, 어떤 것이 최신이 직접 비교할 수 없음
  4. 콘텐츠 기반 해시 생성
    • 해시 키 크기가 크면 GUID처럼 유일할 수 있고, 누구나 생성할 수 있음
    • 장점은 결정적이라는 것인데, 어느 노드에서든 같은 데이터에 대해 같은 해시를 생성할 수 있음
    • 단점은 어떤 것이 최신인지 비교할 수 없고, 길이가 길어질 수 있음
  5. 마지막 업데이트의 타임스탬프
    • 카운터와 마찬가지로 짧고, 어떤 것이 최신인지 비교할 수 있음
    • 단일 마스터도 필요없음
    • 그러나 각 노드의 시간을 동기화해야함
    • 타임 스팸트 간격이 너무 크면 중복되는 위험이 있음. 1ms에 많은 업데이트가 발생하는 경우 ms의 타임스팸트를 사용하는 것은 좋은 방법이 아님

2. 다중 노드에서의 버전 스탬프

  • 단일 서버나, 마스터-슬레이브 복제 처럼 기준 데이터가 단일 노드에서 관리되는 경우 기본적인 버전 스탬프도 잘 작동함
    • 버전 스탬프는 마스터가 제어하고 슬레이브는 마스터의 버전 스탬프를 따름
  • 그러나 피어-투-피어 분산 모델에서는 버전 스탬프를 제어하는 단일 지점이 없어 다른 방법이 필요함

  • 어떤 데이터를 두 노드에 요청시 다른 값을 얻을 가능성이 있음
  • 만일 한 노드에만 반영되고 다른 노드에 반영되지 않았다면 나중 데이터를 선책하면 끝

  • 비일관적 업데이트 때문에 발생했다면 다음과 같이 처리해야함
    1. 카운터
      • 노드가 데이터를 업데이트할 때 마다 카운터를 증가시켜 버전 스탬프에 넣음
      • 단일 마스터에 버전 스탬프가 큰 값으로 선택
  1. 모든 노드가 버전 스탬프의 히스토리를 가짐
    • 마스터가 여럿이거나, 분산 버전 관리 시스템에서 사용하는 방법
  2. 타임스탬프
    • 간단하지만 모든 노드가 시간을 똑같이 맞추기 어렵고 업데이트가 빈번하게 발생하는 경우 특히 문제가 발생함
    • 단일 마스터 환경에서는 제대로 동작하며 보통은 카운터 쓰는 것이 더 안정성이 높음
  3. 벡터 스탬프(vector stamp)
    • 피어-투-피어 시스템에서 가장 흔하게 사용하는 방식
    • 벡터 스탬프는 각 노드의 카운토로 구성된 카운터의 집합
      • 세 노드(blue,green,black)의 벡터 스팸트는 [blue:43, green:54, black:12] 같은 형식
    • 각 노드는 자신의 노드에서 업데이트가 발생할 때마다 자신의 카운터를 증가시킴
    • 두 노드가 통신할 때는 언제나 벡터 스팸프를 동기화함
    • 벡터 스탬프는 비일관성을 발견하는데 요긴하지만, 해결하지는 못함
  • 이는 일관성/지연 사이의 절충의 일부임
  • 즉, 네트워크 분단이 발생할 때 전체 시스템을 사용하지 못하게 할 것인지, 아니면 비일관성을 탐지하고 적절히 처리할 것인지
  • 둘 중 하나를 선택해야함