531. 2PC 블로킹 한계와 코디네이터 다운
⚠️ 이 문서는 분산 트랜잭션을 완벽하게 일치시키기 위해 고안된 2단계 커밋(2PC) 프로토콜이, 만약 중앙에서 지휘를 내리는 '코디네이터(Coordinator)' 서버가 갑자기 벼락을 맞아 죽었을 때, 전 세계의 참가자 서버들이 자물쇠(Lock)를 쥔 채 영원히 굳어버리는 끔찍한 '블로킹(Blocking)' 현상을 다룹니다.
(※ 462번 문서에서 2PC의 기본 구조를 다루었으며, 이 문서는 2PC의 치명적 결함인 동기적 블로킹 문제를 심화로 다룹니다.)
핵심 인사이트 (3줄 요약)
- 본질: 2PC는 코디네이터의 지시에 따라 모든 노드가 일사불란하게 움직이는 동기식(Synchronous) 중앙 통제 알고리즘이다.
- SPOF (단일 장애점): 이 구조는 코디네이터 한 명에게 모든 권력이 집중되어 있기 때문에, 코디네이터가 뻗어버리면 전체 시스템이 마비되는 치명적인 취약점을 가진다.
- 블로킹(Blocking)의 저주: 코디네이터가 죽기 직전에 "준비(Prepare)" 명령을 내렸다면, 참가자 노드들은 데이터를 잠가둔 채(Lock) 코디네이터가 깨어나서 "커밋해!"라고 말해줄 때까지 무한 대기 상태에 빠진다.
Ⅰ. 개요: 지휘자가 기절한 오케스트라 (Context & Necessity)
코디네이터(C)가 서울 서버(A)와 뉴욕 서버(B)에게 분산 트랜잭션을 지시하고 있다.
- C (코디네이터): "얘들아, 각자 계좌 업데이트할 준비해! (PREPARE)"
- A, B (참여자): "오케이! 계좌에 자물쇠(Lock) 걸고 준비 완료! (VOTE_COMMIT)"
- C (코디네이터): "좋아, 둘 다 준비됐구나! 그럼 이제..."
이때, 코디네이터 서버 C에 벼락이 떨어져서 기절해 버렸다. A와 B는 미쳐버린다. "우리 자물쇠 걸고 기다리고 있는데... 커밋하라고? 롤백하라고? 지휘자님 언제 깨어나셔?"
A와 B는 코디네이터가 며칠 뒤 복구될 때까지 쥐고 있던 자물쇠를 풀지 못한다. 결국 서울과 뉴욕의 계좌 시스템은 다른 사람들도 아예 쓸 수 없게 완전히 마비(Blocking)된다.
📢 섹션 요약 비유: 2PC의 블로킹은 **'줄다리기 심판의 기절'**과 같습니다. 심판이 "준비~ 쏘세요!" 해야 하는데 "준비~" 하고 기절해 버렸습니다. 양 팀은 밧줄을 팽팽하게 쥔 채로 심판이 깨어날 때까지 땡볕에서 화장실도 못 가고 영원히 벌을 서고 있어야 합니다.
Ⅱ. 코디네이터 다운 시나리오 분석 ★
코디네이터가 언제 죽느냐에 따라 참가자들의 운명이 결정된다.
1. 1단계(Prepare) 완료 전에 죽음
- 코디네이터가 "준비해!"라고 말하기도 전에 죽었다.
- 결과: 참가자들은 아직 자물쇠를 안 걸었으므로 쿨하게 그냥 없던 일로 치면 된다. (안전함)
2. 1단계(Prepare) 후, 2단계(Commit) 전에 죽음 🚨 최악의 상황
- 코디네이터가 "준비해!"라고 했고, 참가자들은 "준비 완료!"라고 대답했다. (자물쇠 채워짐)
- 그런데 다음 명령(Commit / Rollback)이 오지 않는다.
- 결과: 참가자들은 코디네이터가 깨어날 때까지 무한 대기(Blocking)한다. 참가자끼리 귓속말해서 "야, 우리 걍 커밋할래?"라고 합의할 수도 없다. 만약 다른 참가자가 "난 준비 안 됐어(Abort)"라고 대답했을 수도 있기 때문이다.
3. 2단계(Commit) 명령을 내린 직후에 죽음
- 코디네이터가 "커밋해!"라고 쏘고 장렬히 전사했다.
- 결과: 참가자들은 명령을 받았으므로 자물쇠를 풀고
COMMIT을 완료한다. (안전함)
Ⅲ. 2PC의 한계를 극복하려는 시도들
이 끔찍한 무한 대기(Blocking) 문제를 해결하기 위해 학자들은 여러 가지 꼼수를 제안했다.
1. 타임아웃 (Timeout) 도입
- 참가자가 "1분 기다려도 코디네이터가 응답 없으면 그냥 롤백해 버리자!"라고 시간을 정해둔다.
- 실패: 만약 코디네이터가 죽은 게 아니라 네트워크가 1분 동안 느렸던 거라면? 롤백해 버렸는데 코디네이터가 갑자기 "커밋해!"라고 명령하면 데이터가 완벽하게 박살 난다.
2. 3단계 커밋 (3PC - Three-Phase Commit)
- 코디네이터가 죽었을 때 참가자들끼리 귓속말해서 상태를 유추할 수 있도록, 2PC 사이에 **'Pre-Commit'**이라는 예비 단계를 하나 더 끼워 넣은 마법의 알고리즘이다. (상세 내용은 532번 문서에서 다룸)
- 한계: 너무 복잡하고 핑퐁(통신) 횟수가 늘어나 속도가 더 느려져 실무에서는 안 쓴다.
┌──────────────────────────────────────────────────────────────┐
│ 2PC 코디네이터 다운(SPOF)으로 인한 Blocking 발생 시각화 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [ 👨⚖️ 코디네이터 C ] [ 🇰🇷 A 서버 ] [ 🇺🇸 B 서버 ] │
│ │
│ 1. PREPARE ────────────────────────▶ 🔒 락 걸고 준비 🔒 락 걸고 준비 │
│ 2. ◀──────────────────────── (VOTE_COMMIT 응답) │
│ │
│ 3. 💥 벼락 맞음! (사망) │
│ │
│ 4. (무응답) ───────────────────────▶ ⏳ 기다림 ⏳ 기다림 │
│ (A, B 통장 무한정 사용 불가 마비 상태!)│
└──────────────────────────────────────────────────────────────┘
Ⅳ. 결론
"중앙 통제 시스템은 뇌사(Brain Dead) 상태에 빠지면 사지가 마비된다." 2PC는 관계형 데이터베이스(RDBMS)가 여러 대로 늘어났을 때 완벽한 무결성을 지키기 위해 고안된 고전적인 프로토콜이다. 하지만 이 이론은 '서버는 언제든 죽을 수 있다'는 클라우드 시대의 진리를 간과했다. 코디네이터라는 단일 장애점(SPOF)에 시스템의 운명을 맡기는 이 동기적(Synchronous) 블로킹 방식은, 마이크로서비스(MSA)처럼 수십 개의 서버가 얽히고설킨 현대 아키텍처에서는 결코 버틸 수 없는 낡은 동아줄이 되었다.
📌 관련 개념 맵
- 기반 개념: 2PC (Two-Phase Commit - 462번 문서)
- 발생 문제점: SPOF (Single Point Of Failure), Blocking (블로킹, 자원 잠금 유지 현상)
- 대안 알고리즘: 3PC (Three-Phase Commit - 532번 문서), Saga Pattern (534번 문서)
👶 어린이를 위한 3줄 비유 설명
- 2PC는 반장(코디네이터)이 반 친구들(참여자)에게 "모두 숨 참아!(Prepare)" 하고 지시를 내리는 거예요.
- 친구들은 숨을 꾹 참고(Lock) "준비됐어!"라고 손을 들죠.
- 근데 반장이 갑자기 양호실로 뛰어가 버렸어요(코디네이터 죽음). 반장이 "이제 숨 쉬어!(Commit)"라고 말 안 해주면, 친구들은 얼굴이 파래질 때까지 영원히 숨을 참아야 한답니다(블로킹)!