분산 트랜잭션·합의·일관성 모델
서로 다른 저장소에 있는 A 지갑에서 100원을 빼고 B 지갑에 100원을 넣는 설명용 서비스를 생각하자. 한쪽만 확정되면 안 된다는 업무 규칙을 먼저 가정한다. A 저장소는 성공을 알렸는데 B 저장소의 응답이 끊겼다면, 사용자는 송금이 끝났는지 알 수 있을까? 서버를 복제해 두었다는 사실만으로 이 문제가 해결될까?
송금의 세 보장을 구분하며 읽기
1. 여러 곳의 성공을 하나로 말하려면
서로 다른 저장소에 있는 A 지갑에서 100원을 빼고 B 지갑에 100원을 넣는 설명용 서비스를 생각하자. 한쪽만 확정되면 안 된다는 업무 규칙을 먼저 가정한다. A 저장소는 성공을 알렸는데 B 저장소의 응답이 끊겼다면, 사용자는 송금이 끝났는지 알 수 있을까? 서버를 복제해 두었다는 사실만으로 이 문제가 해결될까?
여기에는 세 질문이 있다. 관련 변경들을 함께 확정할 수 있는지, 복제된 결정이 서로 모순되지 않는지, 그리고 사용자의 읽기가 어느 변경까지 반영해야 하는지다. 이 절은 세 질문을 구별한 뒤 같은 설계 안에서 연결한다. 금액·노드·시각·장애 순서는 원리를 설명하기 위해 만든 가상 사례이며 실제 금융기관의 업무정책이나 실험 결과가 아니다.
확정 결과와 응답 도착은 달랐다
시간초과·재시도·멱등성과 부분실패에서 시간초과는 응답을 기다린 한도를 넘었다는 관측이며, 상대 작업의 실패를 증명하지는 않았다. 같은 논리적 요청의 중복 효과를 막는 멱등성도, 서로 다른 저장소의 성공을 하나로 묶어 주지는 않는다는 경계를 가져온다.
작업의 경계와 복제의 경계를 가져온다
트랜잭션의 네 성질(ACID)의 트랜잭션과 ACID는 관련 작업의 완료·규칙·간섭·지속을 구분했고, DBMS 구조·질의최적화·동시성·복구는 그 보장을 DB 내부의 동시성·복구에 연결했다. 복제·파티셔닝·샤딩의 복제는 같은 자료의 사본을 늘리고 샤딩은 자료의 담당 범위를 나누었으므로, 사본 수와 한 업무에 참여하는 저장소 수를 같게 세지 않는다.
전부 성공하는 문제와 같은 결정을 유지하는 문제
분산 트랜잭션과 합의는 부분실패가 가능한 여러 노드에서 관련 변경의 완료 여부와 복제된 결정의 일치를 조정하는 메커니즘을 다루는 개념군이다. 이 문장에서 완료의 조정과 결정의 일치는 연결되어 있지만 같은 보장이 아니다. 먼저 각각의 대상부터 정한다.
지갑 A의 돈만 줄고 지갑 B의 돈이 늘지 않는 경우와, 같은 지갑 A의 서버들이 서로 다른 잔액을 확정하는 경우를 떠올려 보자. 앞의 경우는 서로 다른 변경들의 결말을, 뒤의 경우는 사본들이 따를 하나의 결정을 맞추어야 한다.
분산 트랜잭션(distributed transaction)은 변경을 독립적으로 확정·취소하는 둘 이상의 관리 단위가 하나의 논리적 작업에 참여하는 트랜잭션이다. 여기서는 각 저장소의 변경을 전부 확정하거나 전부 취소해야 하는 경우를 중심으로 읽는다. 지갑 A와 B가 서로 다른 DB에서 관리된다면 한 송금에 두 관리 단위가 참여한다. 두 DB 중 하나에 사본이 세 개 있더라도 송금의 두 참여자가 세 참여자로 바뀌는 것은 아니다.
이제 지갑 A 하나의 서버 사본들만 따로 보자. 그 사본들이 어떤 변경을 먼저 확정할지 다르게 판단하면 “같은 지갑의 사본”이라는 약속을 유지하지 못한다.
합의(consensus)는 여러 노드가 제안된 값에 관해 결정하되, 결정한 노드들이 서로 다른 값을 확정하지 않도록 하는 문제다. 예를 들어 같은 지갑을 복제한 서버들이 로그의 같은 위치에 서로 다른 명령을 확정하면 안 된다. 합의에서 어떤 값을 선택해도 되는지와 어떤 장애까지 진행할 수 있는지는 별도 조건이다. “송금 참여자 전원의 준비”와 “복제 서버 다수의 동의”를 바꾸어 쓰지 않는 것이 이 절의 출발점이다.
결정하는 역할과 자기 자원을 지키는 역할
자원 관리자(resource manager)는 자신이 맡은 데이터 변경을 확정하거나 취소하고 그 결과의 복구를 책임지는 관리 단위다. 지갑 A와 B를 각각 맡는 DB가 이 사례의 두 자원 관리자다.
이 두 DB에 “전체 송금을 확정해도 되는가”를 묻고 답을 모으는 역할도 필요하다. 각 DB가 자기 변경을 책임지는 역할과 전체 결정을 조정하는 역할을 나누어 보자.
조정자(coordinator)는 참여자의 준비 결과를 모아 전체 완료 결정을 관리하는 역할이다. 참여자(participant)는 자기 자원의 변경을 준비하고 전체 결정에 따라 완료하는 자원 관리자다. 지갑 사례에서는 송금 완료 결정을 관리하는 역할과 A·B 지갑 DB의 역할을 나눈다. 역할을 나눴다는 것은 반드시 프로세스나 컴퓨터도 하나씩만 사용한다는 뜻은 아니다.
조정자는 참여자가 준비하지 못한 변경을 말로 성공시킬 수 없다. 참여자도 자기 쪽이 준비됐다는 이유로 다른 쪽의 상태를 추정해 전체 성공을 선언할 수 없다. 다음 그림의 화살표는 업무 데이터 자체를 복제하는 선이 아니라 준비 요청·응답·완료 결정을 전달하는 선이다.
하나의 송금, 두 참여자, 하나의 완료 결정
상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.
사용자 응답, 조정자의 기록, 두 참여자의 적용은 서로 다른 사건이다. 준비 요청·완료 결정과 준비 응답을 구분해 따라간다. A와 B는 서로 다른 자원이며 각 지갑의 사본 수는 이 그림 밖의 별도 복제 설계다.
두 지갑 DB는 서로 다른 자료를 담당한다. 어느 DB의 사본을 몇 개 둘지는 이 그림과 별도의 복제 설계다. 사용자의 응답 수신, 조정자의 결정 기록, 두 DB의 결정 적용은 서로 다른 사건이며 동시에 발생한다고 가정하지 않는다.
2. 2단계 커밋은 준비와 결정을 분리한다
2단계 커밋(Two-Phase Commit, 2PC)은 참여자들의 준비 가능 여부를 확인한 뒤 전체 커밋 또는 중단 결정을 전달하는 원자적 완료 프로토콜이다. “먼저 모두 준비할 수 있는지 묻고, 그다음 하나의 결정을 따른다”라고 읽으면 된다. 어느 한 참여자가 반드시 필요한 변경을 거부했다면 나머지의 찬성표가 더 많아도 전체 커밋 조건을 충족하지 못한다.
준비 완료(prepared)는 참여자가 이후의 커밋 결정을 이행할 수 있도록 필요한 상태를 보존하고 최종 결정을 기다리는 상태다. 이는 사용자에게 송금 성공을 확정해도 된다는 뜻이 아니다. 준비가 끝난 참여자는 결정을 모르는데도 자기 판단으로 변경을 버려서는 안 된다. 준비와 커밋의 차이가 장애 때의 대기와 복구를 설명한다.
1단계: 나중에도 결정을 이행할 준비를 한다
조정자가 참여자에게 준비를 요청하면 참여자는 자기 변경을 커밋할 수 있는지 검사한다. 가능하다면 복구에 필요한 준비 상태를 먼저 안정적인 저장장치에 남긴 뒤 준비 완료를 알린다. 불가능하면 거부를 알린다. 여기서는 노드가 멈췄다가 보존한 기록으로 복구하는 장애 모형을 사용한다.
기록하기 전에 준비 완료부터 보내면, 재시작한 참여자가 약속의 내용을 잃을 수 있다. 또한 준비한 변경과 충돌하는 작업은 사용한 동시성 제어에 따라 기다려야 할 수 있다. “검사를 한 번 통과했다”와 “나중의 결정을 이행할 책임을 보존했다”는 다르다.
2단계: 전원의 준비를 확인한 뒤 결정을 남긴다
필수 참여자 전원이 준비 완료를 알렸다면 조정자는 커밋 결정을 안정적으로 기록한 뒤 참여자에게 전달한다. 거부가 있거나 아직 커밋 결정이 없는 상태에서 준비 응답을 확보하지 못해 중단하기로 했다면 중단 결정을 따르게 한다. 참여자는 받은 결정에 따라 자기 변경을 완료하고 필요한 자원을 해제한다.
기록된 커밋을 전달하는 중 일부 응답이 사라졌다고 전체 결정을 취소로 뒤집지 않는다. 이미 다른 참여자는 그 결정에 따라 커밋했을 수 있기 때문이다. 복구의 목표는 새 결정을 투표하는 것이 아니라 기록된 같은 결정을 끝까지 전달하고 적용하는 것이다.
100원의 이동과 결정의 이동을 따로 보자
가상 송금 T100의 처음 잔액은 A=500원, B=200원이다. A는 400원으로 바꿀 준비를, B는 300원으로 바꿀 준비를 한다. 전원이 준비했다고 해서 이 두 값이 모든 외부 조회에 곧바로 확정값으로 보인다는 뜻은 아니다. 읽기 노출은 함께 채택한 격리·조회 경계가 결정한다.
초기 확정 상태 A=500, B=200, 합계=700
전원 준비 + 커밋 결정 없음 각 참여자는 결정 대기
기록된 COMMIT를 모두 적용 A=400, B=300, 합계=700
기록된 ABORT를 모두 적용 A=500, B=200, 합계=700
금지할 최종 결과 A=400, B=200, 합계=600합계 계산은 두 참여자의 최종 상태를 비교한 설명용 검사다. 실제 두 DB를 순서대로 읽어 합계를 계산할 때까지 자동으로 같은 시점의 조회가 보장된다는 의미는 아니다. 원자적 완료의 최종 결과와 도중의 읽기 격리는 함께 설계하되 구별해서 검증한다.
준비 뒤의 시간초과는 임의 취소 허가가 아니다
A와 B가 모두 준비 완료를 보낸 뒤 조정자와 연락이 끊겼다고 하자. A가 관찰한 현상만으로는 조정자가 커밋을 기록하기 전에 멈췄는지, 커밋을 기록하고 B에만 전달했는지 구별되지 않을 수 있다. 두 경우에 같은 “응답 없음”이 나타나지만 안전한 후속 동작은 기존 결정에 달려 있다.
A가 기다리기 싫다는 이유로 준비를 취소했는데 B는 이미 커밋했다면 전체 원자성이 깨진다. 이것이 기본 2PC에서 준비된 참여자가 최종 결정을 확인하지 못해 멈출 수 있는 이유다. 결정을 확인할 수 있는 다른 참여자나 복구된 조정자의 기록이 있으면 그것을 이용할 수 있지만, 그런 정보가 항상 남아 접근 가능하다고 가정하지 않는다.
장애를 하나의 “실패”로 합치지 않는다
| 관측한 위치 | 이미 정해진 사실 | 안전한 후속 처리의 기준 |
|---|---|---|
| 준비를 약속하기 전 거부 | 해당 참여자가 준비할 수 없음 | 전체 중단 경로로 조정 |
| 준비 완료 뒤 결정 미확인 | 참여자는 준비 책임을 보존 | 기록된 결정을 찾고 임의 취소 금지 |
| 커밋 결정 뒤 일부 전달 실패 | 전체 결정은 이미 커밋 | 같은 결정을 재전달·복구 적용 |
| 사용자 응답만 유실 | 내부 결정 여부는 별도 확인 대상 | 같은 요청 식별자로 결과 조회·중복 효과 방지 |
이 표는 영구적인 모든 저장장치 손실이나 관리자의 강제 휴리스틱 결정을 안전하다고 승인하지 않는다. 운영자는 준비된 작업의 나이·보유 자원·결정 기록·전체 참여자 목록을 함께 확인해야 한다. 대기를 줄이려고 한 DB에서만 준비를 강제 해제하는 조치는 정상 복구와 구별한다.
2PC의 두 단계와 2PL의 두 단계는 목적부터 다르다
DBMS 구조·질의최적화·동시성·복구의 2PL은 잠금을 얻고 놓는 순서를 규율해 동시 실행의 간섭을 통제했다. 여기의 2PC는 여러 참여자의 완료 결정을 조정한다. 두 단계라는 이름이 같다고 같은 프로토콜로 설명하지 않는다.
원자적으로 함께 커밋하더라도 업무 규칙이 잘못됐거나 전역 격리가 부족하면 잘못된 송금을 함께 확정할 수 있다. 반대로 각 DB에서 올바른 격리를 사용해도 서로 다른 DB의 완료를 별도로 확정하면 한쪽만 남는 문제가 생길 수 있다. 필요한 전역 동시성 제어와 완료 조정을 함께 정하고, 2PC 하나에 ACID 전부의 보장을 몰아주지 않는다.
얻는 것은 완료의 일치이고, 치르는 것은 조정과 대기다
기본 2PC는 참여자 전원의 준비와 결정 기록·전달을 요구한다. 따라서 왕복 통신, 안정적인 기록, 준비 중의 자원 보유가 비용이 된다. 한 업무에 불필요하게 많은 저장소를 참여시키거나 사용자 입력을 기다리는 긴 작업까지 같은 경계에 넣으면 장애 때 묶이는 범위도 커진다.
가능한 업무 경계에서 하나의 DB 트랜잭션으로 규칙을 지킬 수 있는지 먼저 검토한다. 실제로 여러 저장소가 필요하다면 참여자·조정자 복구와 미완료 작업의 운영 절차까지 설계한다. 전원이 살아 있어야 모든 복제 알고리즘도 진행한다는 결론은 아니다. 다음의 합의는 같은 자료를 복제한 노드들의 결정을 다루는 다른 층이다.
여기까지의 결론: 2PC는 여러 참여자의 최종 결론을 맞추며, 준비와 커밋은 다르다. 조정자의 결정을 복구 가능하게 만드는 방법은 다음의 복제 합의와 연결되지만, 참여자 전원의 준비 조건이나 별도의 격리 요구를 없애지는 않는다.
3. 합의는 사본들이 다른 결정을 확정하지 못하게 한다
복제 로그(replicated log)는 같은 상태를 관리할 서버들이 순서에 맞추어 보존·적용하는 명령 기록이다. 같은 처음 상태에 같은 명령들을 같은 순서로 적용하고 처리 규칙도 결정적이라면 같은 결과를 만들 수 있다. 예를 들어 각 사본이 “잔액 500에서 100 차감”을 같은 위치의 명령으로 적용하는 것이다. 기록을 받아 저장한 상태와 실제 상태에 적용한 상태는 구별한다.
그런데 명령을 보내던 서버가 중단되면 누가 그 기록을 이어 관리해야 할까? 새 담당자를 정하는 과정에서도 이미 확정한 명령을 잃지 않게 해야 한다.
Raft는 리더 선출·로그 복제·안전성 규칙을 결합해 복제된 명령 순서를 관리하는 합의 알고리즘이다. 여기서는 구성원이 고정된 복제 집합, 정해진 규칙을 따르는 노드, 중단 후 필요한 상태가 보존되는 장애를 가정한다. 노드가 서로 다른 거짓 정보를 보내는 악의적 장애까지 이 설명으로 처리하지 않는다. Raft 로그를 썼다는 사실과 여러 샤드의 업무가 원자적으로 완료된다는 사실도 같지 않다.
과반수는 수식 하나가 아니라 기록 보존 규칙과 만난다
정족수(quorum)는 정해진 결정을 인정하는 데 필요한 참여 집합의 조건이다. 고정된 Raft 투표 노드가 5개라면 과반수는 3개다. 5개 중 3개인 두 집합은 적어도 하나의 노드를 공유한다. 그러나 이 교집합 계산만으로 같은 위치에 서로 다른 값이 확정되지 않는다고 증명할 수는 없다.
겹치는 노드가 자신이 했던 선택을 잊거나 모순되는 요청에 다시 동의한다면 숫자만 맞아도 이전 결정을 지키지 못할 수 있다. 따라서 투표와 기록을 어떤 규칙으로 보존할지 정해야 한다.
Raft의 임기(term)는 리더 선출 시도를 구분하는 증가하는 논리적 번호다. 노드는 한 임기에 투표를 하나의 후보에게만 주고, 필요한 임기·투표·로그 상태를 보존한다. 후보의 로그가 충분히 최신인지 확인하는 선출 제한과 로그의 앞부분 일치 확인도 함께 작동한다. “아무 서버 세 대가 찬성했다”가 아니라 어떤 임기의 어떤 기록을 보존하며 찬성했는지를 읽는다.
리더가 명령을 받았다는 것과 명령이 확정됐다는 것
리더는 새 명령을 자기 로그에 넣고 다른 사본에 복제를 요청한다. 다른 노드는 앞선 로그의 위치·임기를 확인해 이어 붙일 수 있는지 판단한다. 리더는 자신의 현재 임기 항목이 과반수에 복제되는 등 Raft의 커밋 조건을 만족하면 확정 위치를 전진시키고 순서대로 적용하게 한다.
이전 임기의 항목은 단순히 지금 과반수에서 발견했다는 이유만으로 같은 방식의 직접 확정 판정을 하지 않는다. 현재 임기 항목을 안전하게 확정하면 그 앞의 일치하는 기록도 함께 확정되는 규칙이 중요하다. 구현 세부를 생략하더라도 “노드 수만 세면 안전하다”라는 설명으로 바꾸어서는 안 된다.
5개가 3개와 2개로 갈라졌다면
고정 투표 구성원은 A·B·C·D·E이고 A가 예전 리더였다고 하자. 연결이 {A,B}와 {C,D,E}로 나뉘면 A는 살아 있어도 새 항목을 확정할 과반수를 얻을 수 없다. {C,D,E}는 서로 통신하고 선출 조건·시간 조건이 충족되면 새 리더를 선출해 진행할 수 있다. “3개가 있으니 즉시 항상 성공한다”가 아니라 필요한 프로토콜 조건 아래의 진행 가능성이다.
전체 구성원 5개 → 필요한 과반수 3개
{A,B} : 2 < 3 → 새 로그 확정 불가
{C,D,E} : 3 ≥ 3 → 유효한 선출·기록 규칙 아래 진행 가능A가 이미 리더였다는 과거 사실로 최신 권한을 보장받지는 않는다. 통신이 회복되면 더 높은 임기와 로그 규칙을 통해 오래된 상태를 정리한다. 로그 안전성을 위해 기다리는 것과 모든 요청을 언제나 완료하는 것은 다른 목표다.
참여자 두 곳과 사본 다섯 개를 섞어 세지 않는다
| 구별할 질문 | 기본 2PC | 이 절의 Raft |
|---|---|---|
| 관리하는 대상 | 서로 다른 자원의 한 트랜잭션 완료 | 같은 상태를 위한 복제 로그의 결정 |
| 핵심 조건 | 필수 참여자 전원의 준비 뒤 전체 결정 | 임기·로그·선출 규칙을 지킨 과반수 복제 |
| 대표적인 멈춤 | 준비 뒤 최종 결정을 확인하지 못함 | 안전한 진행에 필요한 과반수와 통신을 확보하지 못함 |
| 자동으로 얻지 못하는 것 | 모든 격리·업무 규칙·무중단 | 여러 샤드의 원자적 업무·모든 읽기의 최신성 |
송금의 A DB가 5개 사본 중 3개에서 상태를 지켰어도 B DB가 준비를 거부했다면 전체 송금을 커밋할 근거가 되지 않는다. 반대로 조정자의 결정을 합의로 복제하면 조정자 하나의 중단에 대한 내성을 높일 수 있지만, 참여자의 준비 조건과 결과 전달 책임은 남는다. 둘을 무조건 대체 관계나 동의어로 설명하지 않는다.
조정 상태를 복제해도 필요한 지갑을 건너뛸 수는 없다
설계자는 조정자의 결정 기록과 각 지갑의 상태를 각각 복제할 수 있다. 이 경우 “어느 서버 한 대가 멈췄는가”보다 “필요한 복제 집합에서 결정을 복구하고 자원을 준비할 수 있는가”를 확인한다. 조정 기록을 복구했다면 그 기록과 모순되지 않도록 나머지 참여자를 완료시켜야 한다.
합의를 이용한 원자적 완료 알고리즘은 별도로 설계할 수 있지만, 조정자 저장소를 복제했다는 사실만으로 아무 설계나 그런 알고리즘이 되지는 않는다. 영원히 접근할 수 없는 참여자를 무시하고 이미 정해진 커밋의 절반만 성공이라고 선언하는 것도 안 된다. 알고리즘 이름보다 장애 모형·보존 기록·전체 완료 조건을 함께 적는다.
4. 사용자가 무엇을 읽을 수 있는지는 별도의 계약이다
일관성의 기존 뜻을 읽기 이력에 적용한다
일관성·응답 지속성·네트워크 분할의 분산 일관성은 읽기·쓰기 결과가 따라야 하는 관찰 규칙이었다. 이제 쓰기의 호출·응답과 다음 읽기의 호출·응답을 나란히 놓아 어떤 결과를 허용하는지 구체적으로 판단한다.
강하다는 말 대신 어느 순서를 지키는지 적는다
선형화가능성(linearizability)은 각 연산이 호출과 응답 사이의 한 순간에 효과를 낸 것으로 설명되면서 객체의 순차적 동작 규칙과 먼저 끝난 연산·나중에 시작한 연산의 실제 시간 선후 관계를 함께 지키는 성질이다. 여기서 순차적 동작 규칙이란 연산을 하나씩 실행할 때 무엇을 반환해야 하는지의 약속이다. 한 값의 저장소에서는 쓰기가 바꾼 값을 뒤의 읽기가 반환하는 규칙을 생각한다. “강한 일관성”은 문맥에 따라 가리키는 보장이 달라질 수 있으므로, 이 절에서 해당 표현을 쓸 때는 이 선형화가능성을 뜻한다고 한정한다.
처음 값이 0이고 다른 쓰기가 없다고 하자. 값 1을 쓰는 작업이 끝난 뒤 읽기를 시작했다면 0을 돌려주는 결과는 이 계약을 어긴다. 모든 컴퓨터의 물리 시계를 똑같이 맞추어야만 정의할 수 있는 성질은 아니다. 실제로 완료된 호출과 뒤에 시작한 호출의 선후 관계가 판단 기준이다.
겹친 읽기까지 무조건 새 값이어야 하는 것은 아니다
단일 값의 처음 상태는 0이고 쓰기는 1로 바꾸는 한 번뿐이다. 다음 시각은 원리를 비교하기 위한 가상 단일 관측 기준이다.
이력 H1: 쓰기 W(1) 호출 1 ─ 응답 2 / 읽기 R 호출 3 ─ 응답 4
R=0은 불가, R=1은 가능
이력 H2: 쓰기 W(1) 호출 1 ───────────── 응답 4
읽기 R 호출 2 ─ 응답 3
R=0 또는 R=1 모두 설명 가능한 순서가 있을 수 있음H1에서는 쓰기가 끝난 뒤 읽기가 시작하므로 W 다음 R이라는 순서를 지켜야 한다. H2에서는 두 연산이 겹쳐 읽기를 쓰기 앞이나 뒤에 놓을 여지가 있다. 이 두 연산만 있는 가정의 결과이며, 다른 읽기·쓰기까지 추가한 전체 이력이 있으면 그 전체에 맞는 하나의 순서를 찾아야 한다.
읽기 하나를 추가한 변형. 처음 값은 여전히 0이고 쓰기는 한 번뿐이라고 하자. W(1)은 1에 호출되어 6에 응답한다. 첫 읽기 R1은 2에 호출되어 3에 값 1로 응답하고, 둘째 읽기 R2는 4에 호출되어 5에 값 0으로 응답했다. 두 읽기가 각각 W와 겹치므로 이 전체 이력도 허용되는가?
먼저 풀어 본 뒤 해설과 교정 보기
해설과 교정. R1이 1을 보려면 하나씩 설명하는 순서에서 W가 R1보다 먼저여야 한다. R1이 끝난 뒤 R2가 시작했으므로 R1이 R2보다 먼저여야 한다. 따라서 W→R1→R2 순서가 필요하지만, 다른 쓰기가 없는 이 가정에서 R2가 0을 보려면 R2가 W보다 먼저여야 하여 모순이다. 전체 이력은 허용되지 않는다. 각 읽기만 따로 보면 겹치니 둘 다 가능이라는 답은 서로 다른 두 설명 순서를 전체에 동시에 사용할 수 있다고 오인한 것이다. 위 H2의 마지막 문장으로 돌아가 모든 연산을 한 줄의 순서에 같이 놓으면 교정할 수 있다.
직렬가능성과 선형화가능성을 바꾸어 쓰지 않는다
DBMS 구조·질의최적화·동시성·복구의 직렬가능성은 여러 트랜잭션의 효과를 어떤 직렬 실행으로 설명할 수 있는지를 물었다. 그것만으로 실제 시간의 완료 선후까지 반드시 같은 순서가 된다고 추가 주장하지 않는다. 선형화가능성은 연산의 호출·응답과 실제 시간 선후를 기준으로 한다.
한 객체의 읽기/쓰기가 선형화가능함
≠ 여러 객체를 바꾸는 업무가 하나의 트랜잭션임
여러 트랜잭션이 직렬가능함
≠ 실제 시간의 완료 순서까지 별도로 확인했음따라서 A와 B의 개별 잔액 읽기가 정확해도 두 읽기 사이에 송금이 진행되면 서로 다른 상태를 조합할 수 있다. 합계 보고서가 필요한 서비스에는 두 지갑을 어떤 일관된 읽기 경계에서 조회할지도 명시한다. “강한 DB”라는 이름 하나로 값 하나·여러 항목·여러 트랜잭션의 보장을 모두 대신하지 않는다.
Raft 리더에게서 읽었다는 사실만으로 최신 읽기는 아니다
앞의 5노드 분할에서 예전 리더 A가 새 리더의 존재를 모른 채 자기 상태만 읽어 줄 수 있다. 새 쪽에서 이미 완료된 변경보다 오래된 값을 돌려주면, 읽기 요청이 A에서 빠르게 끝나더라도 선형화가능성을 만족하지 않는다. 로그를 복제하는 안전성 규칙과 읽기 응답 경로를 함께 점검해야 한다.
Raft 원전의 로그에 새 읽기 항목을 추가하지 않는 방식은 현재 임기의 항목을 확정해 커밋 정보를 확보하고, 과반수와 확인하여 아직 유효한 리더인지 검사하는 추가 조치를 설명한다. 구현에서는 읽기를 수행할 상태에 필요한 확정 항목이 적용되었는지도 보장해야 한다. 시간 기반 임대 방식은 별도의 시계 가정을 요구하므로 과반수 확인과 조건 없이 바꾸어 쓰지 않는다.
최종 일관성은 몇 초 안에 같아진다는 말이 아니다
최종 일관성(eventual consistency)은 새 갱신이 멈추고 필요한 전파·복구와 충돌 처리가 이루어지면 사본들의 상태가 결국 수렴하도록 하는 보장이다. 수렴할 결과를 정하는 규칙도 필요하다. 두 곳에서 같은 항목을 서로 다르게 바꿨다면 어느 변경을 선택하거나 어떻게 병합하는지를 정하지 않고 “나중에 맞춘다”라고만 말할 수 없다.
소개 글의 조회 사본에 변경이 조금 늦게 보이는 것은 허용할 수 있다. 그러나 “최종적”이라는 말만으로 5초나 5분이라는 상한, 자신의 직전 쓰기가 보임, 또는 마지막 좌석의 중복 판매 방지를 얻지는 못한다. 멈춘 통신이 영원히 복구되지 않는 경우까지 무조건 수렴한다고 가정하지 않는다.
내 수정이 사라진 것처럼 보이는 일을 줄인다
자기 쓰기 읽기(read-your-writes)는 같은 관찰 주체의 후속 읽기가 자신이 앞서 완료한 쓰기를 반영한 상태 또는 그 이후 상태를 보도록 하는 보장이다. 소개 글을 고친 본인의 다음 조회만큼은 그 변경을 보이게 하는 경우를 생각하면 된다. 다른 사용자의 모든 읽기가 즉시 같은 변경을 본다는 뜻은 아니다. 나중에 적법하게 다시 변경된 값 대신 본인의 옛 값을 영원히 보여 주라는 뜻도 아니다.
이번에는 본인이 수정하지 않고 다른 사람이 바꾼 새 소개 글을 읽었다고 하자. 다음 조회가 늦은 사본으로 향해 예전 소개 글을 다시 보여 주는 문제는 자기 쓰기만 추적해서는 충분히 막을 수 없다.
단조 읽기(monotonic reads)는 같은 관찰 주체가 이미 본 상태보다 오래된 상태로 후속 읽기가 되돌아가지 않도록 하는 보장이다. 같은 항목을 버전 8까지 보았는데 다음 요청이 늦은 사본으로 가서 버전 7을 보여 주면 문제가 된다. 두 보장은 서로 다른 조건이며, 자신이 쓰지 않은 새 값을 읽은 경우에도 단조 읽기는 의미가 있다.
이 예제의 버전 번호는 하나의 순서로 관리되는 갱신 번호를 가정한다. 서비스는 자신이 완료한 쓰기나 읽은 위치를 추적하고, 그 위치를 반영한 사본으로 보내거나 반영될 때까지 기다리는 식으로 보장을 구현할 수 있다. 사본을 바꾸거나 세션을 새로 만들 때 어떤 문맥을 유지해야 하는지도 계약에 적는다.
5분 지연 제한에는 초과했을 때의 행동도 필요하다
상품 설명에 최대 5분 지연을 허용한다는 가상 계약을 다시 보자. 시각 12:00의 상태를 정확하게 반영한 사본을 기준으로 읽는다면 12:04에는 나이가 4분이지만 12:06에는 6분이다. 기준 시각을 표시했다는 사실만으로 후자까지 5분 제한을 지킨 것은 아니다.
허용 상한 = 300초
기준 상태 이후 240초 → 상한 이내
기준 상태 이후 300초 → 상한 이내
기준 상태 이후 301초 → 상한 초과상한을 넘으면 더 최신인 읽기 경로로 바꾸거나 현재 값 제공을 중단하고 새로 확인 중이라고 알린다. 별도 정책으로 역사적 참고값을 보여 주더라도 5분 이내의 현재 안내라고 표시하지 않는다. 실제 구현에서는 사본이 어느 기준 상태까지 반영했는지와 시간 오차를 확인해야 하며, 마지막 변경의 타임스탬프만을 곧바로 복제 지연으로 간주하지 않는다.
읽기의 목적별로 선택하고 실패 시 행동까지 묶는다
| 가상 서비스의 연산 | 먼저 정할 관찰 계약 | 지킬 수 없을 때의 행동 |
|---|---|---|
| 마지막 좌석의 조건 검사와 확정 | 권한 있는 경로에서 조건 검사와 변경을 하나의 보호된 작업으로 수행 | 성공을 추측하지 않고 확정 불가 또는 결과 미확인 구분 |
| 소개 글의 일반 조회 | 최종 수렴과 허용할 지연·충돌 정책 | 오래된 값 표시·최신 경로 전환 등의 명시된 정책 |
| 본인이 수정한 소개 글 조회 | 자기 쓰기 읽기 | 해당 변경을 반영한 사본을 선택하거나 대기 |
| 이미 본 상태를 다시 조회 | 단조 읽기 | 관찰 위치를 유지해 더 오래된 사본의 응답 제한 |
선형화가능한 읽기와 별도 쓰기를 나누어 사용했다고 해서 그 사이의 경쟁까지 막히는 것은 아니다. 마지막 좌석은 조건 검사와 변경의 결합 및 업무 규칙도 필요하다. 빠른 응답·복제 개수·최종 수렴 중 하나만으로 이 모든 연산을 승인하지 않는다.
5. 모든 업무를 하나의 긴 원자적 작업으로 묶지는 않는다
이미 확정한 일을 다루는 다른 경계
사가(Saga)는 여러 로컬 트랜잭션을 업무 흐름에 따라 완료하고, 중간 실패에 대해서는 이미 완료한 단계의 효과를 보상 작업 등으로 처리하는 장기 업무 조정 방식이다. 재고 확보·결제·배송처럼 독립된 서비스가 참여하고 각 단계의 성공이 외부에 드러날 수 있는 경우를 생각한다. 이것을 하나의 DB 트랜잭션처럼 아무 중간 상태도 보이지 않는 방식이라고 설명해서는 안 된다.
보상 트랜잭션(compensating transaction)은 이미 확정된 작업의 업무 효과를 조정하기 위해 새로 실행하는 트랜잭션이다. 결제가 확정된 뒤 환불을 실행하는 것은 미확정 변경을 취소하는 롤백과 다르다. 원래 결제의 이력이나 외부에서 관찰한 사실까지 지워 주지는 않는다. 되돌릴 수 없는 작업과 보상 실패까지 고려할 수 있을 때에만 업무의 대안이 된다.
예약은 성공했고 결제는 실패했다면
새로운 가상 주문 정책을 명시하자. 결제 완료 전에는 배송하지 않으며, 재고 예약 뒤 결제에 실패하면 예약을 해제할 수 있다고 가정한다. 재고 예약을 로컬로 커밋하고 결제를 요청했는데 결제의 확정된 거절을 받으면 예약 해제를 새 작업으로 실행한다. 결제 응답이 없기만 한 경우에는 먼저 같은 결제 식별자로 실제 결과를 확인한다.
확정된 결제 실패에는 새 예약 해제 작업을 한다 · 상태 따라가기
재고 예약은 이미 자기 저장소의 로컬 거래로 커밋됐으며 결제 결과를 확인한다. 모든 단계에서 예약·로컬 거래·결제·보상의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.
상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.
재고 예약은 이미 로컬 커밋됐다. 결제 성공이면 배송을 준비하고 확정된 실패이면 새 보상 작업으로 예약을 해제한다. 응답 미확인은 같은 결제 식별자로 확인하며 실패로 단정하지 않는다. 보상도 실패할 수 있어 미완료 추적·중복 방지·재시도가 필요하다.
이 예의 조건
- 재고 예약은 이미 로컬 커밋됐다. 결제 성공이면 배송을 준비하고 확정된 실패이면 새 보상 작업으로 예약을 해제한다. 응답 미확인은 같은 결제 식별자로 확인하며 실패로 단정하지 않는다. 보상도 실패할 수 있어 미완료 추적·중복 방지·재시도가 필요하다.
- 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
관계도의 보충 설명
| 대상 | 원 설명 |
|---|---|
| 재고 예약 확정 | 로컬 커밋 완료 |
| 결제 결과? | 확정 결과와 미확인 구분 |
| 배송 준비 | 결제 성공 확인 뒤 |
| 새 보상 작업 | 예약 해제 기존 커밋의 롤백과 구별 |
| 결제 결과 확인 중 | 같은 결제 식별자로 확인 응답 없음은 거절 증거 아님 |
| 연결 | 원 라벨·방향 |
|---|---|
| 재고 예약 확정 → 결제 결과? | 라벨 없는 연결 / 정방향 / 실선 |
| 결제 결과? → 배송 준비 | 성공 / 정방향 / 실선 |
| 결제 결과? → 새 보상 작업 | 확정 실패 / 정방향 / 실선 |
| 결제 결과? → 결제 결과 확인 중 | 미확인 / 정방향 / 실선 |
| 결제 결과 확인 중 → 결제 결과? | 결과 확보 / 정방향 / 실선 |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 예약의 로컬 확정 재고 예약은 이미 자기 저장소의 로컬 거래로 커밋됐으며 결제 결과를 확인한다. |
|
|
| 확정 실패의 보상 요청 공통 결제 판정에서 확정된 실패가 나온 한 경로에서는 예약 해제를 새 보상 작업으로 요청한다. |
|
|
| 실패 경로의 보상 확인 앞 확정 실패 경로에서 요청한 실제 보상 결과와 남은 업무 상태를 확인한다. |
|
|
| 별도 미확인 대안 예약 커밋·결제 판정 전으로 재설정해 응답 미확인인 경우 같은 결제 ID를 조회한다. |
|
|
| 미확인의 재판정 같은 ID의 결과를 확보하면 결제 판정으로 돌아가 성공·확정 실패의 해당 경로를 선택한다. |
|
|
확정된 결제 실패에는 새 예약 해제 작업을 한다 · 상태 따라가기
재고 예약은 이미 자기 저장소의 로컬 거래로 커밋됐으며 결제 결과를 확인한다. 모든 단계에서 예약·로컬 거래·결제·보상의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.
상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.
재고 예약은 이미 로컬 커밋됐다. 결제 성공이면 배송을 준비하고 확정된 실패이면 새 보상 작업으로 예약을 해제한다. 응답 미확인은 같은 결제 식별자로 확인하며 실패로 단정하지 않는다. 보상도 실패할 수 있어 미완료 추적·중복 방지·재시도가 필요하다.
이 예의 조건
- 재고 예약은 이미 로컬 커밋됐다. 결제 성공이면 배송을 준비하고 확정된 실패이면 새 보상 작업으로 예약을 해제한다. 응답 미확인은 같은 결제 식별자로 확인하며 실패로 단정하지 않는다. 보상도 실패할 수 있어 미완료 추적·중복 방지·재시도가 필요하다.
- 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
관계도의 보충 설명
| 대상 | 원 설명 |
|---|---|
| 재고 예약 확정 | 로컬 커밋 완료 |
| 결제 결과? | 확정 결과와 미확인 구분 |
| 배송 준비 | 결제 성공 확인 뒤 |
| 새 보상 작업 | 예약 해제 기존 커밋의 롤백과 구별 |
| 결제 결과 확인 중 | 같은 결제 식별자로 확인 응답 없음은 거절 증거 아님 |
| 연결 | 원 라벨·방향 |
|---|---|
| 재고 예약 확정 → 결제 결과? | 라벨 없는 연결 / 정방향 / 실선 |
| 결제 결과? → 배송 준비 | 성공 / 정방향 / 실선 |
| 결제 결과? → 새 보상 작업 | 확정 실패 / 정방향 / 실선 |
| 결제 결과? → 결제 결과 확인 중 | 미확인 / 정방향 / 실선 |
| 결제 결과 확인 중 → 결제 결과? | 결과 확보 / 정방향 / 실선 |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 예약의 로컬 확정 재고 예약은 이미 자기 저장소의 로컬 거래로 커밋됐으며 결제 결과를 확인한다. |
|
|
| 확정 실패의 보상 요청 공통 결제 판정에서 확정된 실패가 나온 한 경로에서는 예약 해제를 새 보상 작업으로 요청한다. |
|
|
| 실패 경로의 보상 확인 앞 확정 실패 경로에서 요청한 실제 보상 결과와 남은 업무 상태를 확인한다. |
|
|
| 별도 미확인 대안 예약 커밋·결제 판정 전으로 재설정해 응답 미확인인 경우 같은 결제 ID를 조회한다. |
|
|
| 미확인의 재판정 같은 ID의 결과를 확보하면 결제 판정으로 돌아가 성공·확정 실패의 해당 경로를 선택한다. |
|
|
예약 해제도 실패할 수 있으므로 재시도·중복 방지·미완료 상태 추적을 준비한다. 재시도해도 해결되지 않는 업무는 담당자의 확인 대상으로 남긴다. 배송이 이미 시작된 뒤의 취소는 이 가정의 단순 역순 보상으로 해결된다고 말하지 않는다.
2PC와 사가 중 무엇을 고를지는 업무의 허용 범위가 정한다
| 비교축 | 2PC를 포함한 원자적 완료 설계 | 사가 설계 |
|---|---|---|
| 완료 경계 | 참여자들의 전체 확정·전체 취소 | 단계별 로컬 확정과 후속 조정 |
| 중간 상태 | 별도 격리 설계와 함께 노출을 통제 | 이미 확정된 단계가 다른 작업에 보일 수 있음 |
| 장애 후 핵심 | 기존 전체 결정 복구·일치 | 단계 결과 확인·보상·재시도·업무 조정 |
| 적용 판단 | 필요한 자원이 준비 프로토콜을 지원하고 대기를 감당 | 중간 상태와 보상 정책을 업무가 허용 |
사가는 동시 진행하는 업무 사이의 격리를 자동으로 해결하지 않는다. 예약 상태·버전 조건·업무상 확정 시점을 설계하지 않으면 다른 작업이 중간 결과를 최종 성공으로 오해할 수 있다. “빠르므로 사가”나 “돈이므로 언제나 2PC”가 아니라 실제 불변 규칙·참여 시스템의 지원·허용 가능한 복구를 근거로 고른다.
실무 설계 검토표를 하나의 흐름으로 만든다
송금 사례에는 “두 지갑의 변경이 최종적으로 하나만 남지 않는다”는 규칙을 먼저 둔다. 하나의 DB 안에서 그 경계를 충족할 수 있는 대안을 먼저 비교하고, 여러 DB가 필수라면 전체 결정·준비 상태·복구 담당을 설계한다. 각 DB의 복제는 그 상태와 결정을 보존하는 수단으로 연결하되 전체 송금의 완료 조건을 대체하지 않는다.
사용자 응답에는 성공·확정된 거절·처리 결과 미확인을 구별한다. 읽기 경로에는 어느 결과까지 보여야 하는지, 부족할 때 기다릴지 다른 경로로 갈지 실패로 알릴지를 적는다. 검사 지표는 준비 상태의 최장 지속시간, 결정 미적용 참여자 수, 결과 미확인 요청의 나이, 복제 적용 지연, 오래된 읽기 위반, 보상 미완료 건수처럼 실패 원인과 연결한다.
이 지표들은 본 사례의 설계 제안이며 제품 성능의 실측값이 아니다. 성공 응답률만 높이면 준비된 작업이나 보상 실패가 숨어 있을 수 있다. 운영 화면의 녹색 표시보다 결정과 업무 결과를 끝까지 대조할 수 있는지가 중요하다.
6. 이해한 차이를 시험 답안으로 바꾼다
10점 자체 문제: 준비와 결정의 차이
2단계 커밋의 두 단계와 준비 완료 후 장애에서 발생하는 대기의 원인을 설명하고, 2단계 잠금과의 차이를 쓰시오.
공식 기출을 옮긴 문제가 아니라 이 절에서 만든 10점 연습문제다. 요구어는 단계 설명, 장애 원인 설명, 유사 용어 비교의 세 가지다. 준비 요청→지속 가능한 준비→전체 결정이라는 흐름과 준비 상태에서 독단적으로 취소할 수 없는 이유를 먼저 쓴다.
준비·결정 비교 문제의 풀이 보기
10점 목차
- 2PC의 목적: 여러 참여자의 원자적 완료 조정.
- 준비와 결정: 지속 가능한 전원 준비, 결정 기록과 전달.
- 장애의 핵심: 준비 뒤 결과 미확인에서는 임의 취소 금지.
- 2PL과의 차이: 완료 조정과 동시 실행의 잠금 규율을 구분.
10점 도식
전원 준비 뒤 하나의 결정을 기록하고 적용한다 · 상태 따라가기
각 참가자에게 준비를 요청하고 응답을 확인한다. 모든 단계에서 조정자 결정·참가자 상태의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.
상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.
준비 자체는 전체 커밋이 아니다. 필수 참여자 전원 준비이면 COMMIT을 기록하고, 거부·미준비이면 ABORT 경로를 따른다. 두 결정 모두 같은 결정을 전달·적용한다. 이미 기록된 COMMIT을 전달 실패 때문에 뒤집지 않는다.
이 예의 조건
- 준비 자체는 전체 커밋이 아니다. 필수 참여자 전원 준비이면 COMMIT을 기록하고, 거부·미준비이면 ABORT 경로를 따른다. 두 결정 모두 같은 결정을 전달·적용한다. 이미 기록된 COMMIT을 전달 실패 때문에 뒤집지 않는다.
- 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
관계도의 보충 설명
| 대상 | 원 설명 |
|---|---|
| 조정자·준비 결과 | 준비 요청 참여자별 지속 가능한 준비 |
| 전원 준비? | 필수 참여자 기준 |
| COMMIT 결정 기록 | 안정적으로 보존 |
| ABORT 결정 기록 | 거부·미준비 경로 |
| 같은 결정 전달·적용 | 기존 결정 복구 책임 |
| 연결 | 원 라벨·방향 |
|---|---|
| 조정자·준비 결과 → 전원 준비? | 준비 결과 / 정방향 / 실선 |
| 전원 준비? → COMMIT 결정 기록 | 전원 / 정방향 / 실선 |
| 전원 준비? → ABORT 결정 기록 | 미준비 / 정방향 / 실선 |
| COMMIT 결정 기록 → 같은 결정 전달·적용 | 라벨 없는 연결 / 정방향 / 실선 |
| ABORT 결정 기록 → 같은 결정 전달·적용 | 라벨 없는 연결 / 정방향 / 실선 |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| prepare 각 참가자에게 준비를 요청하고 응답을 확인한다. |
|
|
| 지속 결정 모든 준비 조건을 충족하면 COMMIT, 아니면 ABORT를 지속 기록한다. |
|
|
| 같은 결정 전달 확정한 같은 결정을 참가자에게 전달해 반영한다. |
|
|
전원 준비 뒤 하나의 결정을 기록하고 적용한다 · 상태 따라가기
각 참가자에게 준비를 요청하고 응답을 확인한다. 모든 단계에서 조정자 결정·참가자 상태의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.
상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.
준비 자체는 전체 커밋이 아니다. 필수 참여자 전원 준비이면 COMMIT을 기록하고, 거부·미준비이면 ABORT 경로를 따른다. 두 결정 모두 같은 결정을 전달·적용한다. 이미 기록된 COMMIT을 전달 실패 때문에 뒤집지 않는다.
이 예의 조건
- 준비 자체는 전체 커밋이 아니다. 필수 참여자 전원 준비이면 COMMIT을 기록하고, 거부·미준비이면 ABORT 경로를 따른다. 두 결정 모두 같은 결정을 전달·적용한다. 이미 기록된 COMMIT을 전달 실패 때문에 뒤집지 않는다.
- 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
관계도의 보충 설명
| 대상 | 원 설명 |
|---|---|
| 조정자·준비 결과 | 준비 요청 참여자별 지속 가능한 준비 |
| 전원 준비? | 필수 참여자 기준 |
| COMMIT 결정 기록 | 안정적으로 보존 |
| ABORT 결정 기록 | 거부·미준비 경로 |
| 같은 결정 전달·적용 | 기존 결정 복구 책임 |
| 연결 | 원 라벨·방향 |
|---|---|
| 조정자·준비 결과 → 전원 준비? | 준비 결과 / 정방향 / 실선 |
| 전원 준비? → COMMIT 결정 기록 | 전원 / 정방향 / 실선 |
| 전원 준비? → ABORT 결정 기록 | 미준비 / 정방향 / 실선 |
| COMMIT 결정 기록 → 같은 결정 전달·적용 | 라벨 없는 연결 / 정방향 / 실선 |
| ABORT 결정 기록 → 같은 결정 전달·적용 | 라벨 없는 연결 / 정방향 / 실선 |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| prepare 각 참가자에게 준비를 요청하고 응답을 확인한다. |
|
|
| 지속 결정 모든 준비 조건을 충족하면 COMMIT, 아니면 ABORT를 지속 기록한다. |
|
|
| 같은 결정 전달 확정한 같은 결정을 참가자에게 전달해 반영한다. |
|
|
준비 뒤 결정 미확인에서는 기존 결정을 확인하기 전 독단적으로 취소하지 않는다. 2PC는 여러 참여자의 완료 조정, 2PL은 잠금 획득·해제 규율이다.
전원 준비는 커밋 결정의 필요 조건이고, 준비 자체가 전체 커밋은 아니다. 중단 결정의 경우에는 전원이 준비해야 중단할 수 있다는 뜻이 아니다.
10점 답안 예시
2PC는 여러 참여자의 변경을 전부 확정하거나 전부 취소하기 위한 원자적 완료 프로토콜이다. 준비 단계에서 참여자는 복구 가능한 상태를 보존한 뒤 준비 여부를 알린다. 조정자는 전원의 준비를 확인하면 커밋 결정을 기록·전달하며, 준비가 성립하지 않으면 중단 경로를 따른다.
준비 완료 뒤 최종 결정을 확인하지 못한 참여자는 다른 참여자가 이미 커밋했을 가능성을 배제할 수 없다. 따라서 시간초과만으로 임의 취소하지 못하고 결정 복구를 기다릴 수 있다. 이미 기록된 커밋은 일부 전달 실패 때문에 중단으로 뒤집지 않는다.
2PC는 참여자들의 완료를 조정하지만 2PL은 잠금의 획득·해제 순서를 규율하여 동시 실행의 간섭을 통제한다. 그러므로 2PC를 사용했다는 사실만으로 격리 수준이나 업무 규칙의 정확성이 보장된다고 쓰지 않는다.
25점 자체 문제: 세 보장을 결합한 설계
서로 다른 두 지갑 DB의 송금을 설계하시오. ① 한쪽만 최종 확정되지 않게 하는 완료 조정, ② 5개 복제 노드가 3개와 2개로 분할될 때의 결정 원칙, ③ 쓰기 완료 뒤 읽기의 일관성, ④ 준비 상태 및 사용자 응답 유실의 복구를 설명하시오. 중간 로컬 완료와 보상을 허용하는 주문 업무로 요구가 달라지면 사가를 선택할 조건도 비교하시오.
이 문제도 자체 제작이며 실제 회차·빈도를 주장하지 않는다. 두 지갑이 각각 동일한 고정 5노드 구성의 Raft 복제 집합으로 관리된다는 가상 조건을 둔다. 조정자의 결정 기록은 복구 가능하도록 별도로 설계하며, 두 지갑의 전역 격리는 완료 조정과 함께 정해야 한다. 주문 업무의 정책은 예약은 성공했고 결제는 실패했다면의 가정을 그대로 사용한다.
세 보장 통합 설계의 풀이 보기
25점 목차
- 범위와 규칙: 지갑 참여자와 각 지갑의 복제 집합을 구별.
- 원자적 완료: 전원 준비, 결정 기록·전달, 별도의 격리 경계.
- 합의와 분할: 5노드 과반수 3, 임기·로그 규칙, 소수 쪽 새 확정 제한.
- 읽기 계약: 완료 선후를 지키는 선형화가능성, 유효한 리더·적용 상태 확인.
- 복구와 응답: 준비 상태의 결정 대조, 동일 식별자 조회, 성공·거절·미확인 구분.
- 요구 변경과 대안: 중간 상태·보상 실패를 허용할 때의 사가와 운영 지표.
25점 도식
앞의 두 지갑 참여자가 같은 완료 결정을 따른다 그림과 전원 준비·결정 분기를 송금 답안에 사용한다. 송금 요청 식별자는 전체 결정 조정·복구와 연결하며 사용자에게는 관찰 계약을 지키는 읽기로 결과를 제공한다.
| 서로 다른 송금 참여자 | 자기 자료의 복제 집합 | 완료·관찰 경계 |
|---|---|---|
| A 지갑 참여자 | 사본 5, 과반 3 | 준비/전체 결정을 따르고 해당 집합의 합의 규칙을 지킨다. |
| B 지갑 참여자 | 사본 5, 과반 3 | 준비/전체 결정을 따르고 해당 집합의 합의 규칙을 지킨다. |
다른 업무 조건의 재고 예약·결제·배송 준비는 앞의 사가 분기를 사용한다. 실패에서는 먼저 결과를 확인하고, 확정된 실패에 새 보상 작업을 수행한다.
송금 위쪽의 두 참여자는 같은 자료의 사본이 아니다. 각 참여자 아래의 5개 사본이 자기 집합의 과반수 규칙을 따르는 것이며, 양쪽 사본 수를 합쳐 하나의 투표로 송금 성공을 결정하지 않는다.
25점 답안 예시
① 먼저 두 지갑의 변경 중 하나만 최종 확정되지 않는 업무 규칙을 정한다. A·B 지갑은 서로 다른 자원 관리자이고 각 지갑의 5개 노드는 그 지갑 상태의 사본이므로, 트랜잭션 참여자와 합의 투표 노드를 구별한다.
② 원자적 완료에는 기본 2PC의 전원 준비와 전체 결정 기록·전달을 연결한다. 준비 상태는 장애 뒤에도 결정을 이행할 수 있게 보존한다. 커밋 결정 뒤의 일부 전달 실패는 같은 결정의 복구·재전달로 해결하며, 격리와 두 지갑을 함께 읽는 경계는 별도로 설계한다.
③ 고정된 5노드 Raft 집합의 과반수는 3개다. 3대 쪽은 유효한 선출·로그 조건과 통신 조건이 충족되면 진행할 수 있지만 2대 쪽은 새 항목을 확정할 수 없다. 임기별 투표·로그 최신성·현재 임기 항목의 확정 규칙을 지키며, 과반수라는 숫자만으로 안전성을 설명하지 않는다. 각 지갑에서 과반수를 얻어도 다른 지갑의 준비를 생략할 수 없다.
④ 쓰기 완료 뒤 시작한 읽기에는 선형화가능성을 요구한다고 명시한다. 예전 리더의 로컬 상태를 무조건 최신으로 제공하지 않고 유효한 리더 여부와 필요한 확정 항목의 적용을 확인한다. 일반 안내에 최종 일관성을 허용하더라도 지연 상한과 자신의 변경 관찰은 별도 조건으로 정한다.
⑤ 준비 완료 뒤 결정 미확인 상태에서는 임의 취소하지 않고 결정 기록과 참여자 상태를 대조한다. 사용자 응답 유실도 실패로 단정하지 않으며 같은 요청 식별자로 결과를 조회하고 중복 효과를 막는다. 확정된 거절과 처리 결과 미확인을 구별하고 미완료 상태의 지속시간을 관리한다.
⑥ 주문 업무가 중간 로컬 완료와 후속 보상을 허용하면 사가를 비교한다. 결제의 확정된 실패 뒤 예약 해제를 새 작업으로 처리하고, 보상 실패·재시도·중복 방지·담당자 확인을 준비한다. 보상은 기존 커밋의 삭제가 아니며 사가는 전역 격리를 자동 제공하지 않는다. 준비 작업의 나이·미적용 결정·오래된 읽기 위반·보상 미완료를 관찰하여 선택한 보장의 비용과 실패를 확인한다.
근거를 읽을 때의 범위
본문은 아래 원전·공식 설명의 해당 위치를 근거로 재구성했다. 지갑·5노드 분할·읽기 시각·300초 경계·주문 보상 사례는 자체 제작이다. 알고리즘의 정식 증명, 제품 장애 실험, 법적 이용권한 승인을 이 읽기 자료로 대신하지 않는다.
| 근거 ID | 원문과 확인 위치 | 이 절에서 사용하는 범위 |
|---|---|---|
| SRC-DTX-GRAY-LAMPORT-COMMIT | Gray & Lamport, Consensus on Transaction Commit, Microsoft Research 보존본(표지 최종 수정 2017-07-05), §§2–4 | 원자적 완료·기본 2PC의 대기·합의와 완료 조정의 관계 |
| SRC-DTX-RAFT-2014 | Ongaro & Ousterhout, In Search of an Understandable Consensus Algorithm (Extended Version), §§2, 5.1–5.4, 8 | 임기·로그·과반수·클라이언트 읽기 조건 |
| SRC-DTX-HERLIHY-WING-1990 | Herlihy & Wing, Linearizability, §2.2, §3.3 | 호출·응답 선후와 선형화가능성, 직렬가능성과의 구별 |
| SRC-DTX-EVENTUAL-2008 | Vogels, Eventually Consistent — Revisited, Client-side Consistency | 최종 수렴과 관찰 주체별 읽기 보장의 구별 |
| SRC-DTX-AZURE-SAGA | Microsoft Learn, Saga distributed transactions pattern, Solution / Problems and considerations | 로컬 커밋·보상·격리와 보상 실패의 한계 |
| SRC-DTX-PG18-2PC | PostgreSQL 18, §67.4 및 PREPARE TRANSACTION 주의사항 | 준비 상태의 보존·외부 조정·장기 준비 상태의 운영 위험 |
독자는 Raft 확장 원전의 §§5·8에서 로그 안전성과 읽기 확인 조건을, PostgreSQL 18의 준비 트랜잭션에서 외부 조정자·잠금 유지·장기 준비 상태의 주의사항을 확인할 수 있다. Microsoft의 사가 설명은 로컬 커밋·보상·격리의 한계를 연결한다. 원문 열람은 제품 장애 실험이나 독립 승인과 다르다.
30초 정리
여러 저장소의 원자적 완료, 복제 노드의 합의, 사용자가 읽는 결과의 일관성은 서로 다른 질문이다. 준비 완료·커밋 결정·로그 적용·응답 도착을 구별해야 시간초과나 분할에서 잘못된 성공·취소를 피할 수 있다. 업무가 요구하는 최종 결과와 중간 상태의 허용 범위를 먼저 정하고, 다음 절 분산파일·객체저장·데이터레이크에서는 이 판단을 분산파일·객체저장 구조로 이어 간다.