1. 개요

Saga Pattern에 대해 알아보는 시간이다.


2. Saga Pattern이란?

Saga Pattern 2PC를 사용할 수 없는 분산 환경에서 데이터 일관성을 위한 방안이다.

예전에 분산 트랜잭션은 2PC(Two-Phase Commit)을 많이 사용했다. 이는 Prepare-Commit의 두 단계로 이루어져 있습니다. 그리고 2PC는 DB가 분산 트랜잭션을 지원해야 한다. 그리고 같은 DB여야 한다.

하지만 MSA 환경에서는 서로 다른 앱이 API를 통해 트랜잭션을 처리하기 때문에 2PC와 같은 방식은 사용할 수 없다. NoSQL은 분산 트랜잭션을 지원하는 경우가 거의 없다.

그래서 Saga Pattern은 트랜잭션의 관리 주체가 DBMS가 아닌 앱이다. 앱(=마이크로서비스)끼리 이벤트를 주고 받는다. 그리고 각 앱은 자기에게 붙어있는 로컬 DB의 트랜잭션만 신경쓴다. 따라서 각 DB는 다른 제품을 써도 된다.

단 2PC와 다르게 데이터의 원자성이 보장되거나 동기식으로 처리되지 않는다. 그래서 Eventually Consistency만 보장한다. 또한 보상 트랜잭션 처리도 해줘야 합니다.

다음은 Saga Pattern의 종류이다.

2.1. Orchestration 방식

Orchestrator를 중심으로 한 Invoke/Reply 방식이다.만약 트랜잭션이 실패하면 Orchestrator가 그동안의 호출에 대한 보상 이벤트를 호출하여 데이터 정합성을 맞춘다.

  1. 우선 메인이 되는 서비스의 Saga 모듈이 있다.
  2. 트랜잭션에 참가하는 개별 마이크로 서비스들의 로컬 트랜잭션은 Saga Orchestrator에 의해 호출되고, 상태값 설정으로 설정된다.
  3. 참가하는 트랜잭션이 모두 처리된다면, 메인 서비스의 상태가 변경된다.
  4. 단 트랜잭션에 참가하는 특정 마이크로 서비스에서 로컬 트랜잭션 오류 발생하면 Saga Orchestrator는 Rollback service (보상 트랜잭션) 호출한다.

장점은 서비스의 복잡도가 감소한다는 것이다. 

단점은 Orchestrator 추가에 따른 인프라 복잡도 증가, 중간에서의 통제를 위한 복잡한 로직 등이 있다.

2.2. Choreography 방식

각 서비스 간 이벤트를 주고 받는 Event Pub/Sub 방식이다. 중간에 Kafka와 같은 메시지 큐를 통해 비동기 방식으로 전달 가능하다.

  1. 만약 트랜잭션이 실패하면 취소된 앱에서 보상 이벤트를 발행하여 롤백을 시도한다.
  2. 메인이 되는 서비스에서 관련 서비스의 로컬 트랜잭션을 호출한다.

특정 서비스에서 로컬 트랜잭션 오류가 발생하면 해당 서비스에서 자신을 호출한 서비스의 Rollback service 호출한다.

장점은 일단 구축하기는 쉽다는 점이다.

단점은 각 서비스가 이벤트를 리슨하고 있어야 하고, 개별 트랜잭션들이 공통된 공유ID를 정의해야 하고, 이벤트 추적(트랜잭션의 현재 상태를 알기 어려움), 디버그 어려움, 새로운 스텝 추가 시 복잡도 증가 등이 있다.