LLM WikiAccess-protected knowledge portal
← 스터디 홈
1편 · 약 18분

일관성 모델 기초: linearizability, sequential consistency, causal consistency, eventual consistency

분산 시스템에서 "정확한 읽기"란 무엇인가

단일 노드 데이터베이스에서는 쓰기가 성공하면 즉시 읽어도 같은 값이 나온다. 당연해 보이는 이 보장이 분산 시스템에서는 당연하지 않다. Primary에 쓴 값을 Replica에서 읽으면 아직 반영되지 않을 수 있다. 두 클라이언트가 동시에 다른 노드에서 읽으면 서로 다른 값을 볼 수 있다. 타임아웃으로 재시도한 쓰기가 실제로 두 번 적용될 수 있다.

일관성 모델(consistency model)은 이 질문에 답한다. "어떤 읽기가 어떤 쓰기의 결과를 보게 되는가?" 일관성 모델은 시스템과 사용자 사이의 계약이다. 시스템은 약속한 규칙을 지키고, 사용자는 그 규칙 위에서 애플리케이션을 설계한다.

DBA와 플랫폼 엔지니어가 일관성 모델을 알아야 하는 이유는 추상적 이론이 아니다. 복제 지연이 발생했을 때 읽기 Replica에서 읽어도 되는지, Failover 직후 데이터 손실이 얼마나 허용되는지, Kafka에서 읽은 오프셋이 실제로 커밋된 것인지—이 모든 판단의 근거가 일관성 모델에 있다.


일관성 스펙트럼

일관성 모델은 강함에서 약함으로 펼쳐지는 스펙트럼이다. 강할수록 사용자가 예측하기 쉽고, 약할수록 시스템이 더 높은 성능과 가용성을 제공할 수 있다.

Linearizability 실시간 순서 보장
전역 단일 순서
CAP의 "C"
Sequential Consistency 프로그램 순서 보장
실시간 제약 없음
Lamport 1979 정의
Causal Consistency 인과 관계 연산만
같은 순서 보장
독립 연산은 순서 무관
Eventual Consistency 갱신 없으면
결국 수렴
언제 수렴하는지 보장 없음
← 강함 (낮은 성능, 단순한 앱 로직) 약함 (높은 성능, 복잡한 앱 로직) →
일관성 모델 스펙트럼

Linearizability: 가장 강한 실용 모델

Linearizability는 모든 연산이 어떤 한 시점에 즉각 효력을 발휘하는 것처럼 보이는 속성이다. 연산이 시작되고 완료되는 사이 어느 한 순간에 원자적으로 실행된다고 보면 된다.

실용적 의미는 두 가지다.

  1. 읽기는 항상 최신 쓰기를 반영한다. 클라이언트 A가 x = 42를 쓰고 완료 응답을 받은 뒤, 클라이언트 B가 x를 읽으면 반드시 42 이상의 값을 읽어야 한다.
  2. 전역 단일 순서가 존재한다. 모든 연산을 하나의 타임라인에 정렬할 수 있고, 그 순서는 실제 실시간 순서와 일치한다.

CAP 정리에서 말하는 Consistency는 바로 Linearizability를 뜻한다. 데이터베이스가 강한 일관성을 보장한다고 할 때 보통 이 수준을 말한다.

실세계 예시:

  • etcd, ZooKeeper: Raft/ZAB 합의 기반으로 linearizable 읽기와 쓰기 제공. Kubernetes는 etcd의 linearizability에 의존한다.
  • MySQL with synchronous replication (rpl_semi_sync_source_wait_point = AFTER_SYNC): 쓰기가 적어도 하나의 Replica에 복제된 후 커밋 확인. 완전한 linearizability는 아니지만 strong consistency에 근접.
  • PostgreSQL with synchronous_commit = on + synchronous standby: 유사한 효과.

Linearizability의 비용: 모든 쓰기에 대해 전역 순서를 결정해야 하므로 레이턴시가 올라간다. 특히 지리적으로 분산된 클러스터에서는 노드 간 왕복 시간이 쓰기 레이턴시에 직접 더해진다.


Sequential Consistency: 프로그램 순서는 지킨다

Sequential Consistency는 Leslie Lamport가 1979년 정의한 모델로, 각 프로세스 내의 연산 순서는 보장하지만 다른 프로세스와의 실시간 순서는 보장하지 않는다.

예를 들어 클라이언트 A가 x = 1 다음 y = 2를 썼다면, 다른 클라이언트는 반드시 x = 1을 본 뒤에 y = 2를 볼 수 있다. 하지만 클라이언트 A의 쓰기가 다른 클라이언트 B의 동시 쓰기보다 먼저 보이리라는 보장은 없다.

멀티스레드 프로그래밍에서 메모리 일관성 모델이 보통 sequential consistency를 목표로 설계된다. 분산 DB에서는 linearizability보다 구현이 쉽고, 단일 클라이언트 관점에서 일관된 읽기를 보장한다.


Causal Consistency: 원인과 결과만 지킨다

Causal Consistency는 인과 관계(causal relationship)가 있는 연산 사이의 순서만 보장한다. 인과 관계가 없는 연산은 노드마다 다른 순서로 볼 수 있다.

인과 관계는 다음 두 경우에 성립한다.

  • 같은 프로세스에서 A 다음 B가 발생하면 A → B 인과 관계
  • 프로세스 P가 A를 읽고 B를 쓴다면 A → B 인과 관계

실용적 예시: 소셜 미디어에서 댓글 A에 답글 B를 달았다면, 답글 B를 읽는 사람은 반드시 원댓글 A도 볼 수 있어야 한다. 그러나 서로 무관한 포스트들은 순서가 달라도 된다.

MongoDB의 causally consistent sessions는 이 모델의 실용 구현 예다. 클라이언트 세션 안에서 인과성을 추적하는 클러스터 시간(cluster time)을 사용해, 같은 세션의 읽기가 직전 쓰기를 반영함을 보장한다.


Eventual Consistency: 언젠가는 같아진다

Eventual Consistency는 가장 약한 유용한 모델이다. 새로운 쓰기가 없으면 결국 모든 Replica가 같은 값으로 수렴한다고 보장하지만, "언제" 수렴하는지는 보장하지 않는다.

장점은 명확하다. 분산 쓰기 시 다른 노드의 확인을 기다릴 필요 없으므로 레이턴시가 낮고 가용성이 높다. 단점도 명확하다. 아직 수렴이 완료되지 않은 시점에 읽으면 stale한 값을 볼 수 있다.

충돌 해소(conflict resolution) 전략이 핵심이다. 동시에 다른 노드에 같은 키를 다른 값으로 쓴 경우, 시스템은 이를 어떻게 합칠지 결정해야 한다.

전략설명예시
Last Write Wins (LWW)타임스탬프가 가장 늦은 값 채택Cassandra 기본값
CRDT교환·결합 법칙 지키는 자료구조로 자동 합산분산 카운터, 분산 집합
Application-side앱이 직접 충돌 감지·해소CouchDB, DynamoDB
Read repair읽기 시 최신 값으로 오래된 Replica 복구Cassandra, Riak

실세계 예시:

  • Apache Cassandra: 기본적으로 eventual consistency. CONSISTENCY QUORUM으로 더 강한 보장 선택 가능.
  • Amazon DynamoDB: 기본 읽기가 eventually consistent. ConsistentRead = true로 strongly consistent 읽기 선택.
  • DNS: 레코드 변경이 전 세계 리졸버에 전파되기까지 TTL만큼 걸린다.

운영 관점에서 일관성 수준 선택하기

이론을 실무로 연결하는 핵심 질문은 세 가지다.

1. 이 데이터를 stale하게 읽어도 되는가?

결제 처리, 재고 차감, 중복 방지 같은 경우는 No. 읽기 Replica에서 읽으면 안 된다. 반면 소셜 피드, 대시보드 집계, 추천 결과 같은 경우는 수 초의 지연을 허용할 수 있다.

2. 쓰기 레이턴시를 얼마나 희생할 수 있는가?

Strong consistency는 쓰기마다 확인(ack)을 여러 노드에서 받아야 하므로 레이턴시가 올라간다. 주문 처리 DB는 수십 ms의 추가 레이턴시를 감수해도 되지만, 실시간 게임 상태 동기화는 안 된다.

3. 충돌이 발생하면 어떻게 해소할 것인가?

Eventual consistency를 선택하면 충돌 해소 전략이 있어야 한다. 전략이 없으면 last write wins로 기존 데이터가 조용히 사라질 수 있다.

DB / 시스템기본 일관성강화 옵션
MySQL (sync replication)Strong (near linearizable)rpl_semi_sync_source_wait_point
PostgreSQL (sync standby)Strongsynchronous_commit = remote_apply
CassandraEventualCONSISTENCY QUORUM / ALL
DynamoDBEventualConsistentRead = true
MongoDBCausal (in session)w: "majority", readConcern: "linearizable"
KafkaSequential (per partition)acks = all, enable.idempotence = true
etcdLinearizable기본값

Linearizability와 Serializability 혼동 주의

데이터베이스 문서에서 자주 나오는 "serializability(직렬화 가능성)"는 일관성 모델과 다른 개념이다.

  • Serializability: 여러 트랜잭션이 동시에 실행되어도 어떤 순차 실행과 동일한 결과를 낸다. 트랜잭션 고립 수준의 가장 강한 단계(ANSI SQL의 SERIALIZABLE 수준).
  • Linearizability: 단일 연산의 원자성과 실시간 순서에 관한 속성. 트랜잭션 범위가 아닌 단일 읽기/쓰기에 적용.

PostgreSQL의 SSI(Serializable Snapshot Isolation)는 Serializability를 제공하지만 Linearizability를 제공하지는 않는다. Linearizability는 단일 노드 외부에 있는 다른 클라이언트가 본 순서까지 다룬다.

가장 강한 결합은 Strict Serializability다: Serializability + Linearizability. FaunaDB, Spanner 같은 NewSQL 시스템이 이를 목표로 한다.


기억할 문장

일관성 모델은 "시스템이 읽기에 어떤 값을 돌려주겠다"는 약속이다. 약속이 강할수록 앱 개발자가 예외를 다룰 필요가 줄어들지만, 시스템이 지불하는 레이턴시와 가용성 비용이 커진다. 운영자는 워크로드별로 어떤 일관성이 필요한지 이해하고, 시스템의 기본값과 설정 가능한 범위를 알아야 한다.

다음 장에서는 일관성과 가용성 사이의 트레이드오프를 정식화한 CAP 정리와 정상 운영 중의 레이턴시 트레이드오프까지 다루는 PACELC 정리를 살펴본다.

References

  • Lamport, L. (1979). How to make a multiprocessor computer that correctly executes multiprocess programs — https://lamport.azurewebsites.net/pubs/multi.pdf
  • Aphyr, "Strong consistency models" — https://aphyr.com/posts/313-strong-consistency-models
  • ScyllaDB, "What are Consistency Models?" — https://www.scylladb.com/glossary/consistency-models/
  • MongoDB Manual, Causal Consistency — https://www.mongodb.com/docs/manual/core/read-isolation-consistency-recency/#causal-consistency
  • Baeldung, "Introduction to Consistency Models" — https://www.baeldung.com/cs/consistency-models
  • Hazelcast Blog, "Navigating Consistency in Distributed Systems" — https://hazelcast.com/blog/navigating-consistency-in-distributed-systems-choosing-the-right-trade-offs/
  • Amazon DynamoDB, Read Consistency — https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html