Spanner: TrueTime 및 외적 일관성

TrueTime은 모든 Google 서버의 애플리케이션에 제공되는 가용성이 높은 분산형 시계입니다1. TrueTime을 사용하면 애플리케이션은 단조롭게 증가하는 타임스탬프를 생성할 수 있습니다. T가 생성되기 전에 T'가 생성되면 애플리케이션은 모든 타임스탬프 T'보다 크다고 보장되는 타임스탬프 T를 계산할 수 있습니다. 이 보장은 모든 서버와 모든 타임스탬프에서 유지됩니다.

TrueTime의 이 기능은 Spanner에서 트랜잭션에 타임스탬프를 할당하는 데 사용됩니다. 특히 모든 트랜잭션에는 Spanner에서 발생했다고 간주되는 순간을 반영하는 타임스탬프가 할당됩니다. Spanner는 멀티 버전 동시 실행 제어를 사용하므로 Spanner 클라이언트는 타임스탬프에 대한 순서 보장을 통해 쓰기를 차단하지 않고도 데이터베이스가 여러 Cloud 리전에 분산되어 있더라도 전체 데이터베이스에서 일관된 읽기를 수행할 수 있습니다.

External consistency

Spanner는 클라이언트에게 트랜잭션에 대해 가장 엄격한 동시 실행 제어 보장을 제공하며 이를 외부 일관성이라고 합니다2. 외부 일관성 하에서는 Spanner가 성능과 가용성을 높이기 위해 실제로 여러 서버(가능한 경우 여러 데이터 센터)에서 트랜잭션을 실행하더라도 시스템은 모든 트랜잭션이 순차적으로 실행되는 것처럼 작동합니다. 또한 다른 트랜잭션이 커밋되기 전에 트랜잭션 한 개가 완료되면 시스템은 클라이언트가 첫 번째 트랜잭션이 아닌 두 번째 트랜잭션의 영향을 포함하는 상태를 절대 인식할 수 없도록 보장합니다. Spanner는 단일 머신 데이터베이스와 시맨틱상 구별할 수 없습니다. 이러한 강력한 보장이 제공됨에도 불구하고 Spanner를 통해 애플리케이션은 성능을 높이는 대가로 약한 보장을 제공하는 데이터베이스와 대등한 성능을 얻을 수 있습니다. 예를 들어 스냅샷 격리를 지원하는 데이터베이스와 마찬가지로 Spanner를 사용하면 읽기 전용 트랜잭션에서 차단되지 않고 쓰기를 계속하고 스냅샷 격리에서 나타날 수 있는 이상 현상을 제거할 수 있습니다.

외적 일관성은 애플리케이션 개발을 크게 단순화합니다. 예를 들어 Spanner에서 은행 업무 애플리케이션을 만들었고 고객 중 한 명이 처음에 당좌 계좌에 50달러, 저축 예금 계좌에 50달러를 가지고 있다고 가정합니다. 애플리케이션은 먼저 저축 예금 계좌에 200달러를 예금하는 트랜잭션 T1을 커밋한 후 당좌 예금 계좌에서 150달러를 인출하는 두 번째 트랜잭션 T2를 발행하는 워크플로를 시작합니다. 또한 하루가 끝날 때 한 계정에 마이너스 잔액이 있으면 다른 계정에서 자동으로 보상되고 모든 계정의 총 잔액이 해당 날짜 중 언제라도 마이너스인 경우 고객에게 벌금을 부과한다고 가정합니다. T1이 완료된 후에 T2 커밋이 시작하므로 데이터베이스의 모든 판독기는 external consistency를 통해 인출 T2 이전에 예금 T1이 발생했다는 사실을 알 수 있습니다. 다른 방법으로 설명하면 external consistency는 누구도 T1 이전에 T2가 발생하는 상태를 알지 못하도록 보장합니다. 즉, 인출할 때 자금이 부족하여 벌금이 발생하는 일이 생기지 않습니다.

단일 버전 스토리지와 엄격한 2단계 잠금을 사용하는 기존 데이터베이스는 외적 일관성을 제공합니다. 하지만 이러한 시스템에서는 애플리케이션이 최신 데이터를 읽으려고 할 때마다('강력한 읽기'라고 함) 시스템은 데이터에 대한 읽기 잠금을 가져와 읽고 있는 데이터에 대한 쓰기를 차단합니다.

타임스탬프 및 다중 버전 동시 실행 제어(MVCC)

쓰기를 차단하지 않고 읽을 수 있도록 Spanner와 다른 수많은 데이터베이스 시스템은 불변 데이터 버전을 여러 개 유지합니다(멀티 버전 동시 실행 제어라고도 함). 쓰기는 쓰기 트랜잭션의 타임스탬프를 갖는 새로운 불변 ​​버전을 만듭니다. 타임스탬프에서 '스냅샷 읽기'는 해당 타임스탬프 이전의 가장 최근 버전 값을 반환하며 쓰기를 차단할 필요가 없습니다. 따라서 버전에 할당된 타임스탬프는 트랜잭션이 커밋된 것으로 관찰될 수 있는 순서와 일치해야 합니다. 이 속성을 '적절한 타임스탬핑'이라고 부릅니다. 적절한 타임스탬핑이 있다는 것은 외적 일관성이 존재한다는 의미입니다.

이전 섹션의 은행 예를 사용하여 적절한 타임스탬핑이 중요한 이유를 알아보겠습니다. 적절한 타임스탬핑이 없으면 T1에 할당된 타임스탬프보다 이전의 타임스탬프가 T2에 할당될 수 있습니다(예: 가상 시스템이 TrueTime 대신 로컬 시계를 사용하고 T2를 처리하는 서버의 시계가 약간 지체되는 경우). 고객이 인출을 시작하기 전에 예금이 끝나는 것을 보았더라도 스냅샷 읽기는 T2에서의 인출을 반영하지만 예금 T1을 반영하지 않습니다.

단일 머신 데이터베이스의 경우 적절한 타임스탬핑을 얻는 것은 쉽습니다(예: 단조적으로 증가하는 전역 카운터에서 타임스탬프를 할당할 수 있음). 전 세계 모든 서버가 타임스탬프를 할당해야 하는 Spanner와 같이 널리 분산된 시스템에서 효율적으로 타임스탬프를 얻는 것은 매우 어렵습니다.

Spanner는 TrueTime을 사용하여 단조롭게 증가하는 타임스탬프를 생성합니다. Spanner는 두 가지 방법으로 이러한 타임스탬프를 사용합니다. 첫째, 전역 통신이 필요 없는 쓰기 트랜잭션의 적절한 타임스탬프로 타임스탬프를 사용합니다. 두 번째, 강력한 읽기에 대한 타임스탬프로 타임스탬프를 사용하여 한 번의 통신에서 강력한 읽기를 실행할 수 있습니다. 여러 서버에 걸쳐 있는 강력한 읽기도 실행할 수 있습니다.

FAQ

Spanner에서 어떤 일관성 보장을 제공하나요?

Spanner는 트랜잭션 처리 시스템에 가장 엄격한 일관성 속성인 외부 일관성을 제공합니다. 파티션 내의 트랜잭션뿐만 아니라 Spanner의 모든 트랜잭션이 이 일관성 속성을 충족합니다. 외부 일관성은 트랜잭션이 순차적으로 실행되는 시스템과 구분될 수 없는 방식으로 Spanner에서 트랜잭션을 실행함을 의미하며 또한 순차적 순서가 트랜잭션이 커밋된 것으로 관찰될 수 있는 순서와 일치함을 말합니다. 클라이언트가 다른 트랜잭션 T1이 완료된 후 트랜잭션 T2가 커밋을 시작하는 것을 확인한 경우 트랜잭션에 생성된 타임스탬프는 직렬 순서에 해당되므로 시스템은 T1의 타임스탬프보다 높은 타임스탬프를 T2에 할당합니다.

Spanner에서 원자성을 제공하나요?

예. 사실, Spanner는 원자성보다 더 강력한 속성인 외적 일관성을 제공합니다. 원자성은 트랜잭션 동작에 대해 아무것도 알리지 않습니다. 원자성은 원자적 읽기 및 쓰기 작업을 지원하는 동시 실행 객체 속성입니다. 데이터베이스에서 '객체'는 일반적으로 단일 행 또는 단일 셀일 수 있습니다. 외적 일관성은 트랜잭션 처리 시스템 속성 중 하나로, 클라이언트는 임의 객체에 대한 다중 읽기 및 쓰기 작업을 포함하는 트랜잭션을 동적으로 합성합니다. 원자성은 트랜잭션이 단일 객체에 대해 단일 읽기 또는 쓰기 작업만 포함할 수 있는 외적 일관성의 특별한 경우로 볼 수 있습니다.

Spanner에서 직렬 가능성을 제공하나요?

예. 실제로 Spanner는 직렬 가능성보다 엄격한 속성인 외적 일관성을 제공합니다. 순차적으로 실행되는 시스템과 구별될 수 없는 방식으로 트랜잭션이 실행되는 경우, 트랜잭션 처리 시스템을 직렬화할 수 있습니다. 또한 Spanner는 일련의 순서가 트랜잭션이 커밋된 것으로 관찰될 수 있는 순서와 일치하도록 보장합니다.

앞에서 사용한 은행 예를 다시 살펴보겠습니다. 고객이 T1 이후 T2를 순차적으로 실행했음에도 불구하고 직렬 가능성만 제공하고 external consistency를 제공하지 않는 시스템에서는 시스템이 이를 다시 정렬할 수 있습니다. 이로 인해 인출 시 자금 부족으로 벌금이 부과될 수 있습니다.

Spanner에서 strong consistency를 제공하나요?

예. 실제로 Spanner는 strong consistency보다 더 강력한 속성인 외적 일관성을 제공합니다. Spanner의 기본 읽기 모드는 '강력함'입니다. 즉, 복제본에서 읽기를 수신하는지에 관계없이 작업을 시작하기 전에 커밋된 모든 트랜잭션 효과를 관찰할 수 있습니다.

strong consistency와 external consistency의 차이점은 무엇인가요?

복제된 객체가 선형화될 수 있으면 복제 프로토콜이 'strong consistency'를 나타냅니다. 원자성과 마찬가지로 'strong consistency'는 '외적 일관성'보다 약합니다. 그 이유는 강력한 일관성은 트랜잭션 동작에 대해 어떠한 정보도 알리지 않기 때문입니다.

Spanner에서 eventual(또는 lazy) consistency를 제공하나요?

Spanner는 eventual consistency보다 훨씬 강력한 속성인 외적 일관성을 제공합니다. 최정 일관성은 보장 수준을 떨어뜨리는 대가로 성능을 높입니다. 최종 일관성은 판독자가 데이터베이스가 실제로 존재하지 않는 상태에서 데이터베이스를 관찰할 수 있음을 의미하기 때문에 문제가 됩니다(예: A 트랜잭션이 B 트랜잭션보다 먼저 일어났어도 읽기가 트랜잭션 B가 커밋되었지만 트랜잭션 A는 커밋되지 않은 상태를 관찰할 수 있음). Spanner는 eventual consistency과 유사한 성능 이점을 제공하지만 일관성 보장 수준이 훨씬 강력한 비활성 읽기를 제공합니다. 이전 버전의 데이터는 변경될 수 없으므로 비활성 읽기는 쓰기를 차단할 수 없는 '오래된' 타임스탬프의 데이터를 반환합니다.

추가 자료

참고

  • 1J. C. Corbett, J. Dean, M. Epstein, A. Fikes, C. Frost, J. Furman, S. Ghemawat, A. Gubarev, C. Heiser, P. Hochschild, W. Hsieh, S. Kanthak, E. Kogan, H. Li, A. Lloyd, S. Melnik, D. Mwaura, D. Nagle, S. Quinlan, R. Rao, L. Rolig, Y. Saito, M. Szymaniak, C. Taylor, R. Wang, and D. Woodford. Spanner: Google's Globally-Distributed Database. In Tenth USENIX Symposium on Operating Systems Design and Implementation (OSDI 12), pp. 261–264, Hollywood, CA, Oct. 2012.
  • 2Gifford, D. K. 분산 컴퓨터 시스템의 정보 스토리지. PhD thesis, Stanford University, 1981.