모놀리식 환경에서는 일반적으로 하나의 중앙 집중식 데이터베이스를 사용하며, 이를 통해 트랜잭션 관리가 이루어진다.
하지만, MSA에서는 하나의 기능이 여러 마이크로 서비스에 걸쳐 수행된다.
- 전체 트랜잭션이 마이크로 서비스의 물리적인 로컬 트랜잭션 여러개가 묶여서 만들어진다.
- 만약 일부 마이크로 서비스가 실패하면 데이터 일관성이 깨진다.
그럼 마이크로 서비스일 때는 트랜잭션을 어떻게 관리해야 할까?
마이크로 서비스일 때는 분산 트랜잭션이 필요하다.
각 서비스가 독립적인 데이터베이스를 가지고, 네트워크 지연 및 실패 가능성이 크기 때문이다.
MSA 환경에서의 트랜잭션 관리 방법에는 크게 2가지가 있다. 이 2가지 방법에 대해 알아보자.
| 2PC(Two-Phase Commit)
2PC는 2단계에 걸쳐서 영속하는 작업을 말한다.
2PC의 구조는 Coordinator(트랜잭션을 조율하는 중앙 컨트롤러), Participants(트랜잭션의 데이터를 관리하는 데이터베이스 노드 또는 서비스)로 이루어져있다.
| 1. 2PC - Prepare Phase
2PC의 첫 번째 단계는 Prepare Phase로 Voting에 해당한다.
- 코디네이터가 모든 참여자에게 트랜잭션을 준비할 수 있는지 확인요청을 보낸다.(PREPARE)
- 각 참여자는 로컬 트랜잭션을 실행하고 결과를 확인한다.
- 트랜잭션이 성공적으로 처리될 수 있다면, 로컬 로그에 Prepared 상태를 저장하고 YES를 응답한다. 실패하면 NO를 응답한다.
| 2. 2PC - Commit Phase
2PC의 두 번째 단계는 Commit Phase로 Commit에 해당한다.
- 코디네이터가 투표 결과를 수집한다.
- 코디네이터가 모든 참여자에게 결정을 전달한다. (모든 참여자가 YES - COMMIT 메시지를 모든 참여자에게 전송, 하나라도 NO라면 ABORT 메시지를 모든 참여자에게 전송)
- 참여자들이 코디네이터로부터 메시지를 받으면 작업을 수행한다. (COMMIT - 트랜잭션 커밋 후 로컬 로그 업데이트, ABORT - 트랜잭션 롤백 및 Prepared 상태 제거)
- 참여자는 작업을 완료 후 코디네이터에게 ACK 메시지를 전송한다.
- 코디네이너는 모든 참여자로부터 ACK를 받으면 트랜잭션 완료 상태로 종료한다.
| SAGA Pattern
SAGA는 MSA에서 가장 널리 사용되는 트랜잭션 관리 패턴 중 하나이다.
SAGA는 여러 서비스 간 작업을 개별 단계로 나누고, 각 단계를 완료할 때마다 커밋하거나 실패 시 보상 작업을 실행한다.
- 하나의 트랜잭션을 여러 단계로 나눈다.
- 각 단계는 로컬 트랜잭션으로 처리된다.
- 단계가 실패하면 보상 작업을 실행하여 데이터를 원래 상태로 복구한다.
SAGA 패턴에는 2가지 방식이 존재한다.
- Choreography : 각 서비스가 이벤트를 발행하고 이를 구독하여 작업을 수행한다. (중앙 제어자 없이, 메시지 큐 이용)
- 중앙 제어자가 없기 때문에 단일 장애점이 없고 각 서비스들이 느슨하게 결합된다.
- 현재 진행 중인 트랜잭션의 상태를 추적하거나 디버깅하기 어렵다.
- Orchestration : 중앙 제어자가 각 서비스들에게 트랜잭션과 보상 트랜잭션을 명령하며 진행하는 방식이다.
- Orchestrator가 단일 장애점이 되고, 모든 서비스에게 결합된다는 단점이 있다.
- 현재 진행 중인 상태를 추적하기 쉽다는 장점이 있다.
+) 토스에서는 무엇을 선택하였을까?
토스에서는 Orchestration 방식을 선택하였다.
- 클라이언트 요청을 받아 환전을 시작하는 환전 서버가 필요했다.
- 현재 진행 중인 환전의 상태를 관리해야 했기 때문이다.
- 예를 들어, 환전 한도를 구현하려면, 현재 진행 중인 환전의 금액과 상태도 추적이 필요했다.
- 따라서, 환전 서버가 Orchestrator가 되는 것이 적합하다고 판단했다.
| 2PC와 SAGA Pattern 비교하기
2PC와 SAGA Pattern을 비교해보자.
- 2PC는 모든 참여자들이 트랜잭션을 열고 가장 느린 참여자의 투표까지 기다려야 한다. (낮은 가용성과 확장성)
- 2PC는 네트워크 지연과 락 대기가 많아 처리 속도가 느려질 수 있다. (여러 트랜잭션이 동시에 락을 대기하면 데드락 발생 가능)
- 특히 Prepared Phase에서 참여자가 락을 유지해야 하므로 동시성이 낮아진다.
- 참여자가 많아질수록 통신 오버헤드가 커져 확장성이 떨어지기도 한다.
- SAGA 패턴은 각 서비스들의 로컬 트랜잭션들만 진행한다. (높은 확장성과 가용성)
- 하지만, SAGA 패턴은 일부 트랜잭션들만 커밋된 중간 상태가 노출되고 롤백을 위한 보상 트랜잭션을 직접 구현해야 한다.
2PC는 Coordinator(코디네이터)에게 강하게 의존하는 구조로, Coordinator 장애가 발생할 경우 시스템 안정성과 트랜잭션 상태 복구에 문제가 생길 수 있다.
구현하려는 서비스의 특성에 맞게 잘 적용시켜야 할 것 같다.
토스 | SLASH 24 - 보상 트랜잭션으로 분산 환경에서도 안전하게 환전하기를 참고하였습니다.
'💻 개발 > Spring' 카테고리의 다른 글
12/11 - TIL : Validation (0) | 2024.12.11 |
---|---|
11/22 - TIL : 영속성 컨텍스트와 Transaction (1) | 2024.11.22 |
11/21 - TIL : Spring Bean과 DIP, DI, Interface (0) | 2024.11.21 |
11/20 - TIL : Spring Cloud와 Load Balancer (1) | 2024.11.20 |
MVC Response - Spring MVC (0) | 2023.12.05 |