hotamul의 개발 이야기

Data Consistency in Distributed Systems (microservices) 본문

etc.

Data Consistency in Distributed Systems (microservices)

hotamul 2023. 10. 13. 21:33

각 서비스 마다 데이터 베이스가 따로 존재하는 Database per service 아키텍쳐를 사용하고 있을 때 각 서비스에 존재하는 데이터 베이스 일관성(consistency)을 어떻게 보장할 수 있을까?

Two-Phase Commit

Two-phase Commit(2PC)이란 여러 서비스에 거쳐 원자성 트랜잭션 commit을 달성하는, 굉장히 고전적인 방법이다. 2PC에서는 일반적으로 단일 서비스 트랜잭션에는 없는 Coordinator(트랜잭션 관리자)를 사용한다.

Coordinator는 각 서비스에 준비 요청을 보내서 commit 가능 여부를 묻게 되고, 서비스의 응답에 따라 commit할지 rollback할지 결정한다. 모든 서비스가 정상적인 OK 응답을 하면 Coordinator는 commit 요청을 전송하고 실제로 commit이 수행된다.

하지만 아래처럼 하나의 서비스(Coordinator 포함)라도 정상적인 상태가 아니면 2PC에 해당되는 서비스가 동시에 blocking 된다는 단점이 있다.

Saga pattern

고전적인 2PC의 문제점을 해결하기 위해 Saga pattern이 등장했다.

아래처럼 Saga pattern은 각 서비스에서 발생하는 local transaction 성공 event를 다른 서비스에 전달한다.

즉 마이크로 서비스들끼리 이벤트를 주고 받아 특정 서비스의 실패가 발생할때 이전까지 완료된 작업에 대해서 보상(complementary) 이벤트를 전달해 분산 시스템 (microservices) 에서 원자성을 보장하는 패턴이다.

각각의 서비스에서의 트랙잭션 실패로 인한 rollback(complementary transaction)은 각 서비스의 애플리케이션에서 구현한다.

이러한 방법으로 microservices에서의 Data Consistency를 달성할 수 있다. 즉 트랜잭션의 관리 주체가 DBMS가 아닌 각 서비스의 애플리케이션인 것이 Saga pattern의 핵심이다.

일반적으로 Saga pattern은 Choreography based, Orchestration based 두 가지 방식이 있다. Choreography based Saga pattern의 경우 각 서비스 마다 local transaction을 관리 하는 로직이 포함되어 있으며 event를 송/수신 할 수 있다. 이 때 event는 Kafka와 같은 메시지 큐를 이용해 비동기 방식으로 전달할 수도 있다. Choreography 방식은 구성하기가 편하지만 현재 transaction 상태를 추적, 확인하기 어렵다는 단점이 있다. 반면 Orchestration based 방식은 별도의 Saga 인스턴스가 존재하며 각각의 서비스로 부터 transaction 수행 결과를 받아 전체 transaction을 종료시키는 역할을 한다. 만약 중간에서 특정 서비스에서 실패하게 되면 Saga 인스턴스가 보상 이벤트를 각각의 서비스에 전달해서 rollback이 발생할 수 있도록 한다. 하지만 orchestration based 방식은 관리를 해야하는 Orchestrator 서비스가 추가되어야 하기 때문에 인프라 구현이 복잡할 수 있다.

 

Saga pattern 이외에도 microservices 시스템에서의 Data Consistency를 위한 Command Query Responsibility Segregation (CQRS)과 같은 pattern도 있다.

 

참고:

Comments