[분산시스템특론] 3. 2단계 커밋 프로토콜

2025. 10. 21. 17:48·CS/분산시스템특론
반응형

계좌 이체 문제

은행에서 돈을 다른 계좌로 이체할 때, 안전하게 이체하는 것은 어려운 일이다.

단순하게 생각하면 내 통장에서 돈을 2000원 감소시키고, 상대방 통장의 돈을 2000원 증가시키면 될 것 같다.

하지만 나와 상대방이 둘 다 같은 액수에 대해 동시에 돈을 감소시키고 증가시켜야 한다는 점을 생각하면 쉽지 않다는 것을 알 수 있다.

 

온라인으로 돈을 보내는 것은 비동기적인 통신이다.

나는 돈을 보냈다고 생각해서 2000원을 감소시켰는데, 상대방은 돈을 받았다는 신호를 못 받아서 돈을 증가시키지 않았다면 나의 잔액만 2000원이 줄어들 뿐이다.

 

돈의 액수에 대한 원만한 '합의' 를 위해서 사이에 중간자를 두는 방법을 생각할 수 있다.

우리나라로 치면 금융결제원 같은 중간자를 두는 것이다.

 

 

안전성과 라이브니스

분산 시스템은 '안정성 (safety)' 과 '라이브니스 (liveness)' 가 반드시 필요하다.

 

안정성 = 기능적으로 원래 동작해야 할 동작이 올바르게 동작하는 것을 말한다.

라이브니스 = 시도한 일이 결국에 반드시 일어나는 것을 말한다.

 

예를 들어 계좌이체 시스템이라면

안정성 관점에서 내가 돈을 보내서 내 계좌에서 돈이 빠졌는데, 상대방 계좌에는 돈이 안들어가는 '잘못된 일이 발생하면' 안된다.

라이브니스 관점에서 내가 돈을 보냈는데, 내 계좌에서 돈이 빠지지도 않고, 상대방 계좌에 돈이 늘어나지도 않으면 안된다. 즉, 아무일도 발생하지 않으면 안된다.

 

 

2-단계 커밋 (2-Phase Commit)

지난 글에서 정리한 '두 장군 이야기' 에서 두 장군이 직접 소통하려고 하는 상황에서는 절대 합의에 이룰 수 없기에 '간주' 하는 정도로 타협을 봐야 했음을 알 수 있었다.

따라서 분산 시스템에는 '합의' 를 이루기 위해서 두 개체 사이에 중간자를 두는 방법을 사용하는데, 이것이 분산 시스템의 제일 기본적인 프로토콜인 2단계 커밋이다.

 

2단계 커밋 프로토콜에서는 중간자로 트랜잭션 코디네이터 (TC, Transaction Coordinator) 라는 개념을 제시한다.

트랜잭션 코디네이터는 서로 합의를 보려는 두 개체 A, B 로부터 트랜잭션 요청을 받는다.

요청은 '트랜잭션' 이기 때문에 원자성을 갖는다. (즉, 트랜잭션 요청사항은 일어나지 않거나, 요청대로 온전히 일어난다.)

 

스트로우맨 프로토콜

이제 계좌 이체 문제를 한번 해결해보자.

이 문제를 해결하는 제일 간단한 프로토콜로는 스트로우맨(허수아비) 프로토콜이 있다.

 

 

돈을 송금하려는 A 는 TC에게 송금을 요청한다.

TC 는 K 은행에서 1000원을 빼고, S 은행에서 1000원을 입금한다.

이렇게 보면 아무런 문제가 없어보인다.

 

하지만 이렇게 문제를 해결하려면 TC, K, S 은행이 모두 살아이었어야 한다는 전제가 필요하다.

실제로는 수시로 서비스에 장애가 발생하여 요청을 처리하지 못할 수도 있다.

따라서 만약 K 는 장애가 발생하고, S 만 정상적인 상황이었다면, 출금은 되지 않고 S 의 잔고만 늘어나는 상황도 발생할 수 있다.

이러면 'K은행에서 S은행으로 1000원을 송금한다' 라는 트랜잭션 요청은 온전히 실행된 것이 아니므로 원자성이 깨지게 된다.

 

 

원자적 커밋 프로토콜 (Atomic Commit Protocol)

이 문제를 해결한 방법이 바로 원자적 커밋 프로토콜이다.

위 스트로우맨 프로토콜의 문제의 원인은 '시스템의 장애가 발생했는지 알 수 없다' 는 데에서 발생했다.

그러면 해결책은 간단하다. 시스템에 장애가 발생했는지 확인하고 나서 요청을 처리하면 된다.

 

 

A 로부터 송금 요청을 받은 TC 는 K, S 은행이 살아있는지 물어본다.

 

 

만약 두 컴퓨터가 모두 살아있다고 응답을 보냈다면, TC는 위에서 본 것처럼 실제 이체 작업을 실행시킨다.

만약 한 컴퓨터라도 살아있다는 응답을 보내지 않았다면, TC는 이 트랜잭션 요청을 처리하지 않는다.

 

 

하지만 이렇게만 하면 여전히 문제가 남아있다.

분산 시스템에서는 안정성과 라이브니스를 보장하는 것이 중요하다.

만약 은행 K, S 가 모두 '예' 를 보낸 상태에서 TC 에 장애가 생겨서 다운되면 어떻게 될까?

 

이럴 때는 트랜잭션을 커밋하기 전에 미리 로그를 써둠으로써 해결할 수 있다. (Write Ahead Log, WAL)

TC 는 두 은행으로부터 모두 '예' 를 받은 뒤, 로그를 작성하여 '송금 작업을 처리해야 한다' 는 것을 기록한다.

만약 이 상태에서 TC에 장애가 생겨 다운되더라도, 다시 복구된 후에는 로그를 보고 송금 작업을 이어서 처리할 수 있다.

 

만약 K 에서는 출금을 했는데, S 에 입금을 하기 전에 다운되었다면 어떨까?

이때도 마찬가지로 '출금하기 전에 로그 작성', '입금 하기 전에 로그 작성' 을 통해서 내가 하려는 작업을 수행하기 전에 로그를 작성해둠으로써 해결한다. 만약 출금을 하고나서 다운이 되었다면, 로그를 보고 출금까지는 했으니 입금만 이어서 진행하면 된다는 것을 알 수 있다.

그리고 이로서 '잘못된 결과가 발생하는 것' 을 막아, 안정성을 지킬 수 있다.

 

그렇다면 라이브니스는 어떻게 보장할 수 있을까?

간단하다. 만약 두 은행으로부터 모두 응답을 받은 뒤라면, 은행에는 커밋한 내용을 수행해야 한다는 로그가 남아있게 된다.

따라서 은행이 다운되었더라도 나중에 복구되었을 때 로그를 확인하고 '결국에는' 원하는 결과대로 계좌 응답을 처리하게 된다.

즉, 장애가 일어난 장비가 '복구만 된다면' 결국에는 원하는 결과가 실행된다.

 

이제 이 상황에서 발생할 수 있는 다양한 예외 생황들을 생각해보자.

 

1. K 은행은 준비가 되었으나, S 은행은 TC로부터 준비 메세지를 받았으나 장애가 발생하여 응답을 보내지 못한 상황

TC 는 S 은행으로부터 일정 시간동안 응답을 받지 못하면, 준비를 취소하라는 요청을 K 은행에게 보낸다.

K 은행은 준비를 취소하고 ACK 를 보내며, 나중에 S 은행이 복구되어 뒤늦게 확인 응답을 보내더라도 TC 는 이미 취소 처리를 햇으므로 다시 S 은행에게 취소하라는 요청을 보내어 아무 일도 일어나지 않도록 만든다.

 

2. K, S 모두 준비가 되었으나, 이후에 S 은행이 다운되어 커밋을 처리하지 못하는 상황

준비가 되었다는 응답을 받은 TC 는 일단 수행해야 할 작업을 K, S 로 전송한다.

만약 S가 중단되어 이를 받지 못하더라도, 일단 TC 로부터 준비가 되었다는 대답은 한 상태이므로, 나중에 복구되어 작업 요청사항을 받게 되면 이를 그대로 수행만 하면 된다.

 

3. K, S 모두 준비가 되었으나, 네트워크 에러로 S은행의 준비가 되었다는 응답 패킷이 유실된 상황

응답을 보낸 시점에서 S은행은 로그로 준비가 된 상태임을 기록해 둔 상태이다.

하지만 TC 입장에서는 S은행이 준비가 되었다는 응답을 받지 못했으므로, 준비를 취소하라는 요청을 두 은행에 보낸다.

따라서 S 은행은 준비를 취소하고 아무일도 일어나지 않는다.

 


 

이처럼 분산 시스템에서는 장애가 언제나 일어날 수 있음을 고려해야 한다.

따라서 어떻게 해야 장애 내성(Fault-Tolerance)을 가지고, 고가용성 시스템을 구현할 수 있을지 고민해야 한다.

반응형
저작자표시 비영리 변경금지 (새창열림)

'CS > 분산시스템특론' 카테고리의 다른 글

[분산시스템특론] 6. 해밍 코드  (5) 2025.10.22
[분산시스템특론] 5. CAP 이론 & FLP 정리  (0) 2025.10.22
[분산시스템특론] 4. 시간 동기화 문제와 램포트 시계  (0) 2025.10.21
[분산시스템특론] 2. 두 장군 이야기  (3) 2025.10.20
[분산시스템특론] 1. AI Agents vs. Agentic AI  (0) 2025.10.20
'CS/분산시스템특론' 카테고리의 다른 글
  • [분산시스템특론] 5. CAP 이론 & FLP 정리
  • [분산시스템특론] 4. 시간 동기화 문제와 램포트 시계
  • [분산시스템특론] 2. 두 장군 이야기
  • [분산시스템특론] 1. AI Agents vs. Agentic AI
에버듀
에버듀
개발은 좋은데 뭘로 개발할까
  • 에버듀
    Blog. 에버듀
    에버듀
  • 전체
    오늘
    어제
    • 분류 전체보기 (615) N
      • 개인 프로젝트 (43)
        • 토이 프로젝트 (3)
        • [2020] 카카오톡 봇 (9)
        • [2021] 코드악보 공유APP (22)
        • [2022] 유튜브 뮤직 클론코딩 (9)
        • [2025] 한글 SQL 데이터베이스 (0)
      • 팀 프로젝트 (22)
        • [2020] 인공지능 숫자야구 (4)
        • [2022] OSAM 온라인 해커톤 (10)
        • [2024] GDSC 프로젝트 트랙 (6)
        • [2025] 큰소리 웹 페이지 (2)
      • CS (335)
        • 자료구조 (19)
        • 어셈블리 (41)
        • 멀티미디어응용수학 (7)
        • 컴퓨터 구조 (29)
        • 알고리즘 분석 (4)
        • 컴퓨터 네트워크 (38)
        • 프로그래밍언어론 (15)
        • HCI 윈도우즈프로그래밍 (26)
        • 기초데이터베이스 (29)
        • 운영체제 (23)
        • 오토마타 (24)
        • 문제해결기법 (11)
        • 블록체인 (22)
        • 소프트웨어공학 (21)
        • 기계학습심화 (12)
        • 컴퓨터그래픽스와 메타버스 (8)
        • 분산시스템특론 (6)
      • 자기계발 (45) N
        • 생각 정리 (23) N
        • 대외활동 (11)
        • 동아리 (7)
        • 자격증 (3)
        • 머니 스터디 (1)
      • 알고리즘 (PS) (107)
        • BOJ (101)
        • Programmers (5)
        • 알고리즘 이모저모 (1)
      • WEB(BE) (8)
        • express.js (1)
        • Spring & Spring Boot (7)
      • WEB(FE) (2)
        • html, css, js (1)
        • React.js (1)
      • Tool & Language (6)
        • Edit Plus (1)
        • Git (1)
        • Python3 (2)
        • Java (2)
      • Infra (12)
        • AWS (1)
        • Oracle Cloud (8)
        • Firebase (2)
        • Network (1)
      • Android (18)
        • Java (6)
        • Flutter (12)
      • Window (2)
        • Visual Studio 없이 WPF (1)
        • MFC (1)
      • 독서 (14)
        • Inside Javascript (7)
        • Database Internals (6)
        • 한 글 후기 (1)
  • 링크

    • github
    • website
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
에버듀
[분산시스템특론] 3. 2단계 커밋 프로토콜
상단으로

티스토리툴바