profile image

L o a d i n g . . .

728x90

이번 포스팅에서는 분산 환경에서의 데이터베이스 일관성에 대해 살펴보겠습니다. 먼저 "일관성"이란 시스템에서 규정한 규칙을 지킬 수 있는 능력을 의미합니다. 이 규칙은 문맥에 따라 달라지므로 일관성 있는 시스템의 조건도 문맥에 따라 의미를 달리합니다. 분산 환경의 데이터베이스에서 말하는 "일관성"은 데이터베이스 ACID의 C(일관성)와는 다른 의미를 지닙니다. 아래에서 이 차이를 살펴보겠습니다.

  • 데이터베이스 ACID의 C는 애플리케이션에서 규정한 규칙 및 데이터베이스 규칙을 지킬 수 있는 능력을 의미합니다. 그러나 ACID의 C는 애플리케이션 도움 없이 데이터베이스 자체적으로 갖출 수 있는 특징이 아니기 때문에 종종 ACID가 아닌 AID가 되어야 한다는 주장이 존재합니다.
  • 분산 환경에서의 데이터베이스의 "일관성"은 CAP 이론의 C를 의미합니다. 이는 여러 노드로 구성되었지만 요청을 단일 노드에서 처리하는 것처럼 보여야 함을 의미합니다(linearizability와 관련). 

분산 환경에서의 데이터베이스 일관성에 대해 더 자세히 살펴보기 전에, 단일 노드에서 데이터베이스 일관성을 어떻게 유지하는지 알아보고, 분산 환경에서 발생할 수 있는 문제와 일관성에 대해 살펴보겠습니다.

 

단일 노드 데이터베이스 일관성 

SQL 표준과 한계 

단일 노드에서 실행되는 데이터베이스는 일관성을 유지하기 위해 isolation level을 활용합니다. SQL 표준에서는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE이라는 isolation level을 정의하고 있습니다. 그러나 데이터베이스와 관련된 문서들을 읽다 보면 isolation level에 대한 정의와 방지할 수 있는 비정상적인 문제가 문서마다 다르다는 것을 확인할 수 있습니다. 특히 MySQL의 경우 REPEATABLE_READ에서도 phantom read 현상을 방지할 수 있습니다. 이는 사실 MySQL의 REPEATABLE_READ가 SNAPSHOT_ISOLATION을 사용하기 때문입니다. 데이터베이스 벤더들이 제공하는 isolation level에 대한 정보가 제각각인 이유는 SQL 표준 문서가 충분한 정보를 제공하지 않기 때문입니다. 예를 들어 SQL 표준은 대표적인 isolation level인 SNAPSHOT_ISOLATION을 정의하지 않고, 발생할 수 있는 비정상적인 문제에 대한 정보도 제한적으로 제공합니다.

 

Isolation Level만으로 충분할까? 

Isolation level은 여러 트랜잭션이 동시에 실행될 때, 트랜잭션 간에 얼마나 격리할지를 조절하는 설정입니다. 예를 들어, READ_UNCOMMITTED의 경우 커밋되지 않은 트랜잭션에서 수정한 데이터를 다른 트랜잭션에서도 읽을 수 있습니다. 이로 인해 트랜잭션들은 서로에게 영향을 미칠 수 있습니다. 반면, SERIALIZABLE의 경우 여러 트랜잭션이 동시에 실행되어도 트랜잭션들을 순차적으로 실행시켜서 격리시킵니다. 그렇다면 분산환경에서도 SERIALIZABLE isolation level을 설정하면 트랜잭션들 간에 영향을 미칠 가능성이 없기 때문에 문제가 발생하지 않을까요? 정답은 NO입니다. 분산환경에서는 동시에 실행되는 트랜잭션뿐 아니라 순차적으로 실행되는 트랜잭션이라도 문제가 발생할 수 있습니다.

분산환경에서 발생할 수 있는 문제

위 상황은 다음과 같이 동작합니다. 

  1. 데이터베이스에 저장된 초기 잔액은 "5000"
  2. 유저는 잔액을 "3000"으로 업데이트 
  3. 업데이트 요청이 완료된 후 유저는 잔액을 조회 
  4. Follower에 복제가 반영되지 않아 유저가 조회한 잔액은 여전히 "5000" 

SERIALIZABLE isolation level을 설정하더라도 분산환경에서 데이터가 비동기적으로 복제되는 상황에서는 위와 같은 다양한 문제가 발생할 수 있습니다. 분산환경에서 발생할 수 있는 다양한 문제를 해결하기 위해서는 isolation level 뿐만 아니라 consistency level을 이해해야 합니다.

 

분산환경 데이터베이스 일관성 

분산환경 데이터베이스의 일관성은 여러 노드로 구성된 시스템이 요청을 처리할 때 단일 노드에서 처리하는 것처럼 보이도록 하는 특성과 관련 있습니다. 이러한 일관성은 정도에 따라 다양한 consistency level로 구분됩니다.

Consistency Level 

https://jepsen.io/consistency

Consistency level 개념은 multi-processor 시스템에서 shared-memory에 저장된 단일 데이터에 대한 읽기와 쓰기 작업에 대한 연구에서 유래되었습니다. 이는 분산환경 데이터베이스에도 적용할 수 있으며, 분산환경 시스템의 일관성을 논의할 때 주로 사용되는 개념입니다.

Strict Consistency(Strict Serializable) 

Strict consistency

Strict consistency model은 다음과 같은 조건을 가정합니다.

  • 시스템은 정확한 시간을 알 수 있으며 요청을 처리하는 스레드들(서로 다른 노드에 위치할 수 있음)의 시간도 모두 동기화된 상태여야 합니다.
  • 쓰기 작업이 요청된 순서와 쓰기 작업이 반영된 순서가 동일해야 합니다. 그 순서는 모든 스레드에서 동일하게 관찰되어야 합니다. 
  • 모든 읽기 작업은 최신 데이터를 조회해야 합니다.

하지만 분산 환경에서는 정확한 시간을 알기는 불가능에 가깝기 때문에 이 모델은 실용적이지 않아 이론적인 모델로 간주됩니다.

 

Linearizable Consistency 

실용적인 모델 중에서 가장 강한 일관성을 보장하는 모델입니다. Strict consistency와 유사하지만, linearizable consistency의 경우 쓰기 작업이 요청된 시점과 해당 작업이 처리된 시점 사이에 간극이 있을 수 있음을 인정합니다.

Linearizable

  • P3의 "R: x=0"은 P1의 "W: x=5"보다 늦게 실행됩니다. Strict consistency를 만족하기 위해서는 P3에서 읽은 x의 값이 5이어야 합니다(Strict consistency는 쓰기 요청이 처리된 시점과 쓰기 요청이 반영된 시점 간 간극이 없음을 가정하기 때문). 
  • P1의 "W: x=5"와 P3의 "R: x=0"은 겹치는(overlap) 기간이 존재합니다. Linearizable consistency의 경우 실행 시점이 겹치는 경우 최신 데이터를 읽어야 한다는 조건이 없기 때문에 위 사진은 linearizable consistency 조건을 만족하는 것으로 볼 수 있습니다. 

 

Sequential Consistency 

Sequential consistency

Sequential consistency는 쓰기 작업이 어떤 스레드에서 처리됐는지와 상관없이 모든 스레드에서 동일한 순서로 처리된 것처럼 보이도록 하는 모델입니다. P3를 보면 P1의 "W: x=5" 작업이 P2의 "W: y=10" 작업보다 먼저 수행되었음을 알 수 있습니다(중간에 "R: y=0"이 존재하기 때문입니다). P4은 x와 y 각각에 대해 최신 값을 읽기 때문에 어떤 값이 먼저 쓰였는지 알 수 없지만, 쓰기 작업의 처리 순서에 있어서 P3와 동일한 global view를 공유한다는 것을 확인할 수 있습니다. 따라서 위 시스템은 sequential consistent 한 시스템이라고 볼 수 있습니다. 

 

Causal Consistency 

Sequential consistency는 서로 관련 없는 쓰기 작업이더라도 모든 스레드가 동일한 쓰기 순서를 관찰해야 한다는 조건을 가집니다. Causal consistency는 그와 반대로, 서로 관련 있는 쓰기 작업만 모든 스레드에서 동일한 순서로 보이면 됩니다.

Causal consistency

Causal consistency 모델에서는 특정 스레드에서 데이터 X를 읽고 데이터 Y에 대한 쓰기 작업을 수행하면 X와 Y는 관련 있는 작업으로 간주됩니다. 또한 X를 읽기 전에 발생한 모든 X에 대한 쓰기 작업은 Y에 대한 쓰기 작업보다 먼저 처리된 것으로 간주됩니다. 위 예시에서 P2는 "R: x=5" 이후 "W: y=10" 작업을 처리합니다. 이 두 작업은 서로 관련이 있는 것으로 간주되고, "R: x=5" 이전의 모든 x에 대한 쓰기 작업은 "W: y=10"보다 이전에 발생한 것으로 간주됩니다. P3만을 고려할 때 causal consistency를 만족하지만("W: x=5"이 "W: y=10" 이전에 실행된 상태를 바라보므로), P4의 경우 "W: y=10"이 "W: x=5"보다 먼저 실행된 상태를 바라보기 때문에 위 사례는 causal consistency를 만족하지 않습니다.

Eventual Consistency 

Consistency level 중 가장 제약조건이 적은 모델은 Eventual consistency입니다. Eventual consistency는 특정 쓰기 작업 이후 오랜 시간(오랜 시간의 정의는 데이터베이스 벤더가 정의합니다)이 지나면 결국 최신 값을 확인할 수 있다는 조건만 존재합니다.

 

마무리 

이번 포스팅을 통해 분산환경에서 발생할 수 있는 문제와 일관성에 대해 살펴보았습니다. 기업형 애플리케이션 개발에서는 데이터베이스를 여러 노드로 구성하는 경우가 많아지고 있습니다. 이러한 상황에서 발생할 수 있는 문제를 미리 인지할 수 있고 해결할 수 있는 개발자가 되기 위해서는 분산환경에 대한 지식이 필수적이라고 생각합니다. 이 포스팅은 아직 부족한 내용이 많기 때문에 참고할 수 있는 문서를 함께 기재해 두었습니다.

 

Reference 

https://fauna.com/blog/introduction-to-transaction-isolation-levels

https://jepsen.io/consistency

728x90
복사했습니다!