Phase 3레슨 13
Distributed Transaction
2PC, 3PC, Saga, TCC — 여러 서비스의 데이터를 어떻게 원자적으로 변경하는가
💡ELI5·
이체를 두 은행에서
A은행: 100 차감 ─┐
├─ 하나의 트랜잭션?
B은행: 100 증가 ─┘
→ 분산 트랜잭션 필요
→ 2PC: 둘 다 준비되면 커밋 (락 발생)
→ Saga: A 차감 → B 증가, B 실패 시 A 보상(복원)💡 비유 — 2PC = 두 사람이 동시에 서명해야 계약 성립 (한 명이 서명 안 하면 대기). Saga = A가 먼저 서명하고 B에게 넘기고, B가 서명 안 하면 A의 서명을 취소(보상).
🔬Deep Dive·
2PC (Two-Phase Commit)
Phase 1 (Prepare): Coordinator → "준비됐나?" → Participant1, Participant2 Participant1: "준비됨" (락 잡음) Participant2: "준비됨" (락 잡음) Phase 2 (Commit/Rollback): Coordinator → "커밋!" → 모두 커밋 또는 하나라도 NO → "롤백!" → 모두 롤백
| 장점 | 단점 |
|---|---|
| 강한 일관성 (원자성 보장) | Coordinator 장애 시 blocking |
| 구현이 비교적 단순 | 글로벌 락으로 성능 저하 |
| 동기 대기로 지연 증가 | |
| 장기 트랜잭션에 부적합 |
🔬Deep Dive·
Saga Pattern
주문 생성 → 결제 → 재고 차감 → 배송 시작
↓ 결제 실패
재고 보상(복원) → 주문 취소
각 단계는 독립적인 로컬 트랜잭션
실패 시 이전 단계를 보상 트랜잭션으로 되돌림| 방식 | 구조 | 장점 | 단점 |
|---|---|---|---|
| Choreography | 이벤트 기반, 중앙 제어 없음 | 결합도 낮음, 확장 용이 | 플로우 파악 어려움, 디버깅 복잡 |
| Orchestration | 중앙 Orchestrator 제어 | 플로우 명확, 디버깅 용이 | Orchestrator SPOF, 결합도 증가 |
🔬Deep Dive·
TCC (Try-Confirm-Cancel)
Try: 잔액 100 예약 (사용은 안 했지만 다른 곳에서 못 쓰게) Confirm: 예약 확정 → 실제 차감 Cancel: 예약 해제 → 잔액 복원
TCC는 Saga와 달리 Try 단계에서 리소스를 예약하므로, 중간 상태에서 다른 트랜잭션이 해당 리소스를 선점하지 못한다. 하지만 모든 서비스가 Try/Confirm/Cancel 인터페이스를 구현해야 하므로 구현 비용이 높다.
🔬Deep Dive·
Outbox Pattern — 이중 쓰기 문제 해결
문제: DB 커밋 + 메시지 전송을 따로 하면 하나만 성공할 수 있음
해결 (Outbox):
DB 트랜잭션:
1. 주문 데이터 INSERT
2. outbox 테이블에 이벤트 INSERT ← 같은 트랜잭션
별도 프로세스:
3. outbox 읽기 → 메시지 큐 전송 → 전송 성공 시 outbox 삭제⚖️Trade-off·
분산 트랜잭션 방식 비교
| 방식 | 일관성 | 성능 | 복잡성 | 적합 |
|---|---|---|---|---|
| 2PC | 강함 | 낮음 (락) | 중간 | 동일 DB, 짧은 트랜잭션 |
| Saga | 최종 | 높음 | 높음 (보상 로직) | 마이크로서비스 |
| TCC | 강함 (예약) | 중간 | 매우 높음 | 리소스 예약 필요 |
| Outbox | 최종 | 높음 | 낮음 | DB+메시지 동기화 |
❓ 체크포인트 질문
- 1.2PC의 Coordinator가 장애 나면 어떤 문제가 발생하는가?
- 2.Saga가 2PC보다 실용적인 이유는?
- 3.Choreography Saga와 Orchestration Saga의 차이는?
- 4.TCC(Try-Confirm-Cancel)가 Saga보다 나은 점은?
- 5.Outbox Pattern이 분산 트랜잭션에서 해결하는 문제는?