[Database] CQRS와 분산 읽기/쓰기 DB 구성, 데이터 일관성 모델 (최종 일관성, 강력한 일관성)
본문 바로가기

ComputerScience/Database

[Database] CQRS와 분산 읽기/쓰기 DB 구성, 데이터 일관성 모델 (최종 일관성, 강력한 일관성)

CQRS (Command and Query Responsibility Segregation)

CQRS는 명령(Command)과 조회(Query) 작업의 책임을 분리하는 패턴이다. 이 패턴의 핵심 아이디어는 다음과 같다.

  1. 명령(Command): 데이터의 상태를 변경하는 작업을 담당한다. 예를 들어, 데이터베이스에 새로운 데이터를 삽입하거나 기존 데이터를 수정하는 작업이다.
  2. 조회(Query): 데이터를 읽는 작업을 담당한다. 데이터베이스에서 데이터를 조회하여 사용자에게 제공하는 역할을 한다.

이 패턴에서 명령과 조회는 서로 다른 모델로 구현될 수 있으며, 심지어 서로 다른 데이터 저장소를 사용할 수도 있다.

기존 데이터베이스 모델의 문제점

데이터베이스의 쿼리와 업데이트에 동일한 데이터 모델을 사용하는 경우, 아래와 같은 문제가 발생할 수 있다.

 
  • 복잡한 애플리케이션에서의 어려움: 읽기 쪽에서 다양한 쿼리를 수행해야 하거나, 다른 형태의 DTO(데이터 전송 개체)를 반환해야 할 때 개체 매핑이 복잡해질 수 있다. 또한, 쓰기 모델에 복잡한 유효성 검사나 비즈니스 로직이 포함되면 모델이 과도하게 복잡해질 위험이 있다.
  • 성능 및 확장성 요구 사항의 불일치: 읽기와 쓰기 작업의 성능 및 확장성 요구 사항이 비대칭적일 수 있다.
  • 데이터 경합: 동일한 데이터 세트에서 병렬 작업을 수행할 때 데이터 경합이 발생할 수 있다.
  • 성능 저하: 데이터 저장소 및 데이터 액세스 계층의 부하와 복잡한 쿼리로 인해 성능이 저하될 수 있다.
  • 보안 및 권한 관리의 복잡성: 동일한 엔터티가 잘못된 컨텍스트에서 데이터에 접근할 수 있어 보안과 권한 관리가 복잡해질 수 있다

CQRS를 사용한 문제 해결

  • 성능 향상: 읽기와 쓰기를 분리하여 각 작업에 최적화된 데이터 저장소와 인프라를 사용할 수 있다. 조회는 읽기 전용 데이터베이스나 캐시를 활용해 빠르게 처리하고, 쓰기는 별도의 데이터베이스에서 관리할 수 있다.
  • 확장성: 읽기와 쓰기 모델을 독립적으로 확장할 수 있다. 조회 요청이 많다면 읽기 모델을 수평으로 확장해 부하를 분산시키고, 쓰기 모델은 별도로 확장해 유연한 확장이 가능하다.
  • 유지보수성: 비즈니스 로직이 명령 모델에 집중되므로 복잡한 상태 변경 로직을 쉽게 관리할 수 있으며, 단순화된 읽기 모델은 유지보수가 용이다.
  • 데이터 일관성: CQRS는 이벤트 소싱과 결합해 데이터 상태 변경을 이벤트로 기록하고, 이를 통해 데이터 일관성을 보장하다. 이벤트를 기반으로 조회 모델을 생성하여 일관성을 유지하면서도 높은 성능을 얻을 수 있다.
  • 최적화된 데이터 스키마: 읽기와 쓰기 모델 각각에 최적화된 데이터 스키마를 사용할 수 있어 설계 및 구현이 간소화된다.
  • 보안 강화: 쓰기 모델에서만 올바른 도메인 엔터티가 데이터 변경 작업을 수행하도록 관리하여 보안을 강화할 수 있다.
  • 관심사의 분리: 읽기와 쓰기 모델의 분리로 유지 보수와 유연성이 향상되며, 복잡한 비즈니스 로직을 더 명확하게 구현할 수 있다.

분산 데이터베이스로서의 읽기/쓰기 분리

개념

데이터베이스에 대한 읽기 요청과 쓰기 요청을 분리하여 각각 다른 서버에 할당함으로써 부하를 분산한다. 이를 통해 읽기 성능을 최적화하고, 쓰기 작업의 영향을 최소화한다.

구조

  • 쓰기 전용 DB (Primary/Master): 모든 쓰기 작업(INSERT, UPDATE, DELETE)이 이곳에서 수행된다. 일반적으로 일관성을 보장하기 위해 단일 노드에서 수행되며, 변경 사항은 읽기 전용 DB에 전파된다.
  • 읽기 전용 DB (Replica/Slave): 주로 읽기 요청을 처리한다. 쓰기 전용 DB로부터 복제된 데이터를 바탕으로 동작하며, 여러 개의 읽기 전용 DB를 배치하여 수평적 확장을 지원한다.

데이터 복제

  • 비동기 복제: 쓰기 전용 DB에서 변경된 데이터를 비동기적으로 읽기 전용 DB에 복제하여 최신 상태를 유지한다. 이 과정에서 일시적인 데이터 불일치가 발생할 수 있지만, 최종적으로 일관성을 유지한다.
  • 동기 복제: 일관성을 더욱 강화하기 위해 쓰기와 동시에 모든 복제본을 업데이트한다. 이는 성능에 영향을 미칠 수 있다.

샤딩과의 차이점

  1. 데이터 분할 방법:
    • 읽기/쓰기 분리는 데이터 자체를 분할하지 않고, 요청 유형(읽기 vs 쓰기)에 따라 데이터베이스를 분리한다.
    • 샤딩데이터를 특정 기준에 따라 물리적으로 분할하여 저장한다.
  2. 목적:
    • 읽기/쓰기 분리는 주로 부하 분산과 성능 최적화를 목적으로 한다. 특히, 읽기 요청이 많은 시스템에서 효과적이다.
    • 샤딩은 데이터의 물리적 분할을 통해 대규모 데이터를 효율적으로 관리하고, 저장 용량을 확장하기 위한 전략이다.
  3. 구조적 복잡성:
    • 읽기/쓰기 분리는 상대적으로 구조가 간단하며, 읽기와 쓰기 부하를 분리하여 관리한다.
    • 샤딩은 데이터 일관성을 유지하기 위해 복잡한 데이터 분할 및 라우팅 메커니즘이 필요하다.

데이터 일관성 모델: 강력한 일관성 (Strong Consistency)

개념

  • 정의: 데이터 변경이 모든 노드에 즉시 반영되어, 모든 클라이언트가 동일한 최신 데이터를 읽을 수 있도록 보장하는 일관성 모델이다.

특징

  1. 즉각적인 일관성: 모든 데이터 쓰기 연산이 즉시 모든 노드에 반영된다. 따라서, 모든 읽기 연산은 최신 데이터를 반환한다.
  2. 동기화: 쓰기 연산 시 데이터가 모든 관련 노드에 동기화되어야 하므로, 데이터 변경에 따른 지연(latency)이 발생할 수 있다.
  3. 트랜잭션 지원: 강력한 일관성을 유지하기 위해 분산 트랜잭션을 지원하며, 일반적으로 2PC(Two-Phase Commit)와 같은 프로토콜을 사용한다.
  4. 사용 사례: 금융 시스템, 은행 거래, 주문 처리 시스템 등 즉각적인 데이터 일관성이 중요한 애플리케이션에 사용된다.

장점과 단점

  • 장점: 항상 최신 데이터 보장, 사용자 경험 일관성 제공
  • 단점: 높은 지연 가능성, 확장성 제약, 시스템 가용성 저하 가능

데이터 일관성 모델: 최종 일관성 (Eventual Consistency)

개념

  • 정의: 모든 데이터 복제본이 일정 시간이 지나면 동일한 상태에 도달한다고 보장하는 일관성 모델이다. 즉, 데이터는 즉각적으로 일관성을 보장하지 않지만, 시간이 지남에 따라 일관성을 확보한다.

특징

  1. 비동기 복제: 데이터 변경 사항이 비동기적으로 다른 노드로 전파되며, 이 과정에서 일시적인 데이터 불일치가 발생할 수 있다.
  2. 시간 경과에 따른 일관성: 네트워크 지연이나 장애가 없는 한, 최종적으로 모든 데이터 복제본이 일관된 상태에 도달한다.
  3. 충돌 해결: 여러 노드에서 동시에 데이터 변경이 발생할 수 있으므로, 충돌 해결 메커니즘(예: 최신 쓰기 승리, 버전 관리)을 통해 일관성을 유지한다.
  4. 사용 사례: SNS 피드, 콘텐츠 전송 네트워크(CDN), 캐시 시스템 등 일관성보다 성능과 가용성이 중요한 시스템에 적합하다.

장점과 단점

  • 장점: 높은 성능과 가용성, 시스템 확장성 증대
  • 단점: 일시적인 데이터 불일치, 복잡한 충돌 해결 필요

데이터 불일치 시나리오

문제: 최신 데이터의 비일관성

  • 상황:
    • 데이터가 Write DB에 기록된 직후, Read DB에 전파되기 전 클라이언트가 데이터 조회를 요청한다.
    • 클라이언트는 Redis에 최신 데이터가 캐싱되지 않거나 캐시 미스로 인해 과거 데이터를 받을 수 있다.
  • 해결 방안: 최종 일관성 방법
    • Redis 우선 업데이트: 모든 쓰기 작업에서 데이터를 먼저 Redis에 기록하여 최신 상태를 캐시한다. 이는 클라이언트가 가장 최근의 데이터를 조회할 수 있도록 보장한다.
    • 데이터베이스에 대한 쓰기 작업이 비동기적으로 수행되며, Redis와의 동기화가 즉시 이루어지지 않으므로, 시스템은 일시적인 데이터 불일치를 허용한다

참조

.