MSA Database

MSA Database

Database Per Service

  • 온라인 쇼핑몰을 개발한다고 가정한다.
  • 대부분의 서비스는 데이터베이스가 필요하다.
  • Order Service 는 주문 관련 정보를 저장한다.
  • Customer Service 는 고객에 대한 정보를 저장하게 될 것이다.

이슈

  • 서비스는 느슨하게 결합 되어야하고, 이들은 서로 독립적으로 개발, 배포, 확장이 되어야한다.
  • 비즈니스 트랜잭션은 반드시 복수 서비스로 확대 되더라도, 상호 영향을 주지 않아야한다. 예를 들어 Place Order 는 고객의 신용도를 넘어서지 않는 범위 내에서 주문이 이루어 지는지 검증해야한다.
  • 비즈니스 트랜잭션은 복수 서비스가 소유하고 있는 데이터에 대한 쿼리가 필요하다. 예를 들면 View Available Credit 은 Customer 의 creditLimit 을 검색해야한다. 그리고 Order 은 주문에 대해서 총 합을 계산해야한다.
  • 복수 서비스가 소유한 데이터를 조인해야하는 경우도 있다. 예를 들어, 특정 영역에 있는 고객을 검색하고, 최근 주문을 조회하기 위해서 고객과, 주문을 조인해야한다.
  • 데이터베이스는 확장을 위해서 복제 본을 가질 필요가 있다.
  • 서로다른 서비스는 데이터 저장을 위한 각기 다른 특징적인 데이터베이스가 필요로 한다. 어떤 서비스는 관계형 데이터베이스가 적합하고, 어떤 서비스는 NoSQL 이 적합할 수 있다.

해결책

  • 마이크로 서비스에서 저장되는 데이터는 API 를 통해서 데이터에 접근할 수 있다.
  • 서비스의 트랜잭션은 오직 자신의 서비스 내에서 트랜잭션이 걸린다.
  • 서비스의 데이터베이스는 서비스 구현의 일부이며, 이들은 직접적으로 다른 서비스의 데이터베이스에 접근할 수 없다.
  • 서비스 저장소에 대한 데이터를 프라이빗 하게 유지하기 위한 몇가지 방법이 있다.
    • 서비스별로 프라이빗 테이블을 가진다. : 각 서비스는 자신이 소유한 테이블을 가지고 있으며, 해당 서비스만이 접근이 가능하다.
    • 서비스 마다 스키마: 각 서비스는 데이터 베이스 스키마를 서비스에서만 접근하도록 할 수 있다.
    • 서비스 마다 데이터베이스: 각 서비스는 자신의 데이터베이스 서버를 가진다.
  • 서비스 마다 프라이빗 테이블과 서비스마다 스키마는 가장 낮은 오버 헤드를 가진다. 서비스별 스키마를 이용하는 것은 오너쉽을 명확히 가진다.
    • 높은 처리량을 위해서는 자신의 데이터베이스 서버가 필요하다.
  • 모듈마다 명확한 영역을 위한 좋은 방법이 있다.
    • 각 서비스마드 사용자 아이디를 가지고, 데이터 베이스의 접근 권한을 이용하여, 데이터베이스를 구분할 수 있다.

결과

  • 서비스 마다 데이터베이스는 다음 이점이 있다.
    • 서비스들끼리 연관을 느슨하게 할 수 있다.
    • 하나의 서비스의 변경이 다른 서비스에 영향을 주지 않는다.
    • 각 서비스는 서비스에 적합한 데이터베이스를 가진다. 예를 들어 텍스트 검색을 위해서는 엘라스틱 서치가 적합하다. 소셜 그래프가 필요하다면 Neo4J 가 적합하다.
  • 서비스 마다 데이터베이스를 가지는 것은 다음과 같은 단점이 있다.
    • 비즈니스 트랜잭션을 구현하기 위해서 복수의 서비스들로 나눠지면 직관적이지 못하다.
    • 분산 트랜잭션은 CAP 이론에 따라서 피해야하는 설계이다.
    • 더우기 많은 현대적인 NoSQL 데이터베이스는 분산트랜잭션을 지원하지 않는다.
    • 데이터 조인을 위한 쿼리 구현은 여러 데이터베이스를 사용할때는 도전이 된다.
    • 복수개의 SQL, NOSQL 데이터베이스를 운영하는 것은 매우 복잡도를 올리게 된다.

Shared Database

  • 복수개의 서비스에서 단일 데이터베이스를 공유하는 방법역시 있다.
  • 각 서비스는 데이터에 편하게 접근할 수 있고, ACID 트랜잭션도 유지할 수 있다.
  • 데이터비이스가 공유 되기 때문에 어떠한 서비스에서도 테이블 데이터에 접근할 수 있게 된다.

장점

  • 직관적인 ACID 트랜잭션으로 데이터 일관성을 유지할 수 있다.
  • 단일 데이터베이스로 오퍼레이션이 단순하다.

단점

  • 서비스들 간의 커플링이 심하다.
  • 테이블 스키마의 변경은 다른 섭비스에 영향을 준다.
  • 여러 서비스가 데이터베이스에 접근하므로, 데이터베이스에 부하를 주는 구조가 된다.

SAGA

  • 각 서비스마다 데이터베이스를 가지고 있는 구조에서 여러 서비스에 트랜잭션 보장이 필요한경우 데이터 일관성 측면에서 어려움이 있다.

2PC (Two phase commit)

  • 2PC 는 한때 도입을 고려한 트랜잭션 보장의 도구였다.
  • 그러나 대용량의 트래픽을 수용하는데 한계가 있으며, 2PC 를 구현하는데 어려움으로 인해 현재는 다른 대안이 필요한 상태이다.

해법

  • 각 비지니스 트랜잭션은 복수개의 서비스로 확장하며 이때 SAGA 를 통해서 트랜잭션 구현을 수행한다.
  • SAGA 는 로컬 트랜잭션들의 시퀀스를 말한다.
  • 각 로컬 트랜잭션은 데이터베이스를 업데이트 하고, 완료 메시지를 보내거나, 다음 트랜잭션으로 넘어가는 방식으로 수행이 된다.
  • 만약 로컬 트랜잭션이 실패가 나면, 비즈니스 룰이 깨지고, 이때 SAGA 는 일련의 보상 트랜잭션이 수행되는 구조로 되어 있다.

SAGA 구현

  • 크로노 그래피(안무) - 각 로컬 트랜잭션은 도메인 이벤트를 발생한다. 이는 로컬 트랜잭션을 다른 서비스로 만들어 낸다.
  • 오케스트레이션(통합) - 오케스트레이터는 어떤 로컬 트랜잭션이 참여하고 있는지를 알려준다.

예제 (크로노 그래피 기반의 사가)

  1. OrderService 는 POST /orders 요청을 수신한다. 그리고 order 를 생성하고, 이 상태는 PENDING 상태가 된다.
  2. Order 가 생성한 이벤트를 보낸다.
  3. Customer Service의 이벤트 핸들러는 예약 크레딧을 수행한다.
  4. 그리고 출금에 대한 이벤트를 발생한다.
  5. OrderService 의 이벤트 핸들러는 승인하거나 리젝을 한다.

예제 (오케스트레이션 기반의 사가)

  1. OrderService 는 POST /order 요청을 수신한다. 그리고 Create Order sata 오케스트레이터를 생성한다.
  2. saga 오케스트레이터는 Order 를 생성하고 PENDING 상태로 만든다.
  3. Reserve Credit 커맨드를 Customer Service 에 전송한다.
  4. Customer Serivce 는 크레딧을 예약한다.
  5. 출금 결과를 응답으로 보낸다.
  6. saga 오케스트레이터는 승인하거나, 리젝한다.

장점

  • 어플리케이션이 데이터 일관성을 여러 서비스에 걸친 작업에도 유지할 수 있도록 해준다.
  • 분산 트랜잭션이 필요가 없다.

단점

  • 프로그램이 복잡해진다.
  • 개발자는 반드시 보상 트랜잭션을 구현해야한다.
  • 서비스의 신뢰도를 위해서 데이터베이스를 자체적으로 업데이트 하고, 메시지와 이벤트를 보낼 수 있도록 해야한다.
  • 이것은 전통적인 분산 트랜잭션을 이용할 수 없다. 데이터베이스 확장 그리고 메시지 브로커 등을 수행할 수 있어야한다.

API Composition

  • MSA 환경에서 데이터의 조인은 API 를 통해서 결과값들을 조합하는 과정을 통해서 최종 결과를 만들어 낸다.

장점

  • 단순한 쿼리로 결과를 가져가서 조압할 수 있게 된다.

단점

  • 쿼리 결과는 비효율적으로 수행된다.
  • 메모리 내 조인은 큰 데이터 셋으로 수행해야할 때 많은 리소스를 사용한다.
  • 네트워크 트래픽을 증가 시킨다.