본문 바로가기

발로 그리는 분산 시스템

Two Phase Commit(2PC)

들어가며..

"Two Phase Commit"(이하 2PC)이란 독립적인 머신에서 구동되는 프로세스들의 분산 트랜젝션 보장을 위한 프로토콜이다. '트랜잭션(transaction)'이란 용어는 주로 DB에서 많이 다루어지는데, 여러 개의 쿼리 실행을 하나의 작업 단위로 보고 모든 쿼리가 성공하거나, 그 중 하나라도 실패하면 모든 쿼리를 취소하는 작업 단위를 의미한다. 이것을 분산 시스템으로 옮겨 오면 독립적인 머신에서 구동 되는 프로세스들에게 동일한 작업들을 적용함에 있어서 모든 프로세스들에게 적용되거나 반대로 아무 프로세스에게도 적용되지 않는 작업단위를 의미한다.

예를 들어 분산 시스템 내에 A, B, C 프로세스가 구동 되고 있다고 가정하자. 프로세스 A에서 발생한 업데이트가 B, C에 도 동일하게 적용 되어 모든 프로세스들이 업데이트에 성공하거나, 그 중 한 프로세스라도 업데이트에 실패 하면 모든 프로세스의 업데이트가 취소되는 것을 트랜잭션이라 한다.

2PC는 분산 시스템의 트랜잭션 보장을 위한 프로토콜이다.

2PC 구성

2PC는 트랜잭션을 관리하는 조정자(coordinator)와 트랜잭션의 대상이 되는 참가자(participant)들로 구성된다. 참고로 조정자(coordinator)는 여러 문서들에서 동일한 용어를 사용하는데 참가자(participant)의 경우에는 집단(cohort), 사이트(site) 등등 다양한 용어로 불리고 있으니 다른 문서를 볼 기회가 있다면 참고 하도록 하자.

조정자(coordinator), 참가자(participant)

2PC 알고리즘

서로 다른 서버 S1, S2, S3, ….Sn에서 구동 되고 있는 분산 데이터베이스들이 있다고 가정하자. 각 서버 Si에서는 모든 데이터베이스 작업에 대한 별도의 로그를 관리하며 각 서버 Si와 매칭 되는 로컬 트랜잭션 Ti들, T1, T2, T3, ... Tn이 있다. 각 트랜잭션 Ti들은 서버 Si에 있는 개별 트랜잭션 매니저가 관리하고 있다.

아래 예제에서 고려해야 할 몇 가지 사항들 :

  • 2PC에서, 우리는 각 사이트들이 각자의 트랜잭션에 대한 로그를 기록하고 있다고 가정한다. 단, 전역적인 로그는 없다
  • 코디네이터(Ci)는 분산 트랜잭션이 중단되거나 커밋되는지 확인하는 데 중요한 역할을 한다.

이 프로토콜에서는 코디네이터(Ci)와 다른 서버 간에 네트워크 통신을 하도록 구현되었다. 그리고 각 메시지가 전송될 때 마다, 복구가 필요한 경우를 대비하기 위해 로그를 남긴다.

1단계 - 준비(prepare) 단계

준비 단계는 코디네이터(coordinator, 조정 프로세스)가 모든 참가자(트랜잭션 대상 프로세스들)들을 대상으로 지금 업데이트가 가능한 상태인지 질의하는 단계다.

  1. 먼저 코디네이터(Ci)는 자신의 로그 레코드에 <Prepare T> 를 기록한다.
  2. 그리고 코디네이터(Ci)는 트랜잭션 T가 수행 되어야 하는 모든 참가자 서버에게 Prepare T 메시지를 보낸다.
  3. Prepare T 메시지를 수신한 각 참가자는 트랜잭션 T를 커밋 할지 중단할지 결정 한다. 참가자가 다른 작업을 하고 있는 경우 응답이 지연 될 수는 있지만 결국 코디네이터(Ci)에게 등답을 보내야 한다.
  4. 참가자가 커밋을 원하지 않으면 <no T> 로그를 기록하고 로컬 트랜잭션 관리자는 Abort T 메시지를 코디네이터(Ci)에게 보낸다.
  5. 사이트가 커밋을 원하면 <ready T> 로그를 기록하고 로컬 트랜잭션 관리자는 Ready T 메시지를 코디네이터(Ci)에게 보낸다. 이제 코디네이터(Ci)가 ready T 메시지를 보내게 되면 코디네이터를 제외하고 트랜잭션 T가 커밋되는 것을 취소 할 수 없다.

2단계– 결정(commit) 단계

두 번째 단계는 트랜잭션 T를 공동으로 실행하는 모든 사이트로부터 코디네이터(Ci)가 abort T 또는 commit T를 받는 것으로 시작된다.

그러나 일부 사이트가 응답하지 않을 수 있다. 다운되었거나 네트워크에 의해 연결이 끊어졌을 수도 있을 것이다. 이 경우 적절한 타임 아웃 시간을 주고, 해당 시간이 지나면 참자자들이 abort T를 보낸 것처럼 처리한다. 트랜잭션의 처리는 다음 사항에 따라 다르게 진행된다.

  1. 코디네이터는 트랜잭션 T의 모든 참가자들로 부터 ready T를 수신하면 트랜잭션 T를 커밋하기로 결정한다. 그러면 코디네이터는 로컬 로그 <Commit T>를 기록하고 T에 관련된 모든 참가자에게 commit T 메시지를 보낸다.
  2. 각 참가자는 commit T 메시지를 받으면 해당 서버에서 트랜잭션 T를 커밋하고 로그 레코드에 <Commit T>를 기록한다.
  3. 사이트가 abort T 메시지를 수신하면 T를 중단하고 <Abort T>를 로그 레코드에 기록한다.
  4. 만일 코디네이터가 하나 이상의 사이트로부터 abort T를 수신한 경우 해당 로그 레코드에 <Abort T>를 기록한 다음 트랜잭션 T와 관련된 모든 참가자에게 중단 abort T 메시지를 보낸다.

개념 자체는 아주 간단하다. 분산 시스템의 중간에 commit을 관리하는 코디네이터가 있고, 트랜잭션이 필요하면 코디네이터가 모든 참가자에게 현재 커밋이 가능한지 물어 본다. 가능하다면 모두 커밋을 진행하고, 불가능하다면 코디네이터는 모든 참가자들에게 롤백을 요청한다.

2PC 단점

  • 2PC의 주요 단점은 코디네이터에 오류가 발생하면 모든 트랜잭션이 코디네이터가 복구 될 때 까지 지연 된다.
  • 트랜잭션 실행 중 코디네이터에 문제가 생겨 응답을 받지 못하면 참가자 전체가 블로킹에 빠지게 된다.
    트랜잭션(T)을 위해 참가자들이 자신의 데이터에 잠금을 걸었지만, 실행중 어떠한 이유로든 코디네이터로 부터 응답을 받지 못하면이 참가자들은 임의로 commit/abort 결정을 할 수 없다. 만일 코디네이터가 정상이고 다른 참가자들은 정상적으로 commit/abort가 결정된 상태에서, 응답을 받지 못한 참가자가 임의로 트랜잭션의 commit/abort를 결정하고 트랜잭션을 종료해버리면 다른 참가자와 다른 결과를 가질 수 있다. 이 때문에 참가자가 코디네이터로 부터 응답을 받지 못하면 코디네이터가 복구되거나 수정될 때까지 최종 결정이 지연 된다. 경우에 따라 복원하는 데 하루 또는 오랜 시간이 걸릴 수 있으며 이 기간 동안 잠긴 데이터 항목은 다른 트랜잭션(Ti)에 액세스할 수 없게 된다.

부록 1. 같이 읽으면 좋은 글

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!