19. 2단계 커밋 코디네이터 장애와 in-doubt 블로킹 (C#)
난이도 최상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 시나리오: 서로 다른 두 샤드에 있는 플레이어 간 아이템 교환을 원자적으로 처리하려고
// 2단계 커밋(2PC)을 쓴다. 코디네이터가 두 참여 샤드에 Prepare 를 보내 자원을 잠그고
// 찬성을 받으면 Commit 을 보낸다. 참여자는 Prepare 후 코디네이터의 결정을 기다린다.
//
// 요구사항:
// - 교환은 원자적이어야 한다(양쪽 다 반영되거나 양쪽 다 취소).
// - 코디네이터나 참여자가 임의 시점에 죽거나 재시작해도 자원이 영구히 잠기거나
// 한쪽만 반영되는 상태로 남으면 안 된다.
// - 잠긴 자원은 유한 시간 안에 반드시 해소되어야 한다.
//
// 과제: Execute 와 참여자 흐름을 검토하고, 코디네이터/참여자가 특정 시점에 실패할 때
// 무엇이 잘못되는지, 어떤 조건에서 드러나는지, 어떻게 고칠지 설명하라. (A)(B)(C) 를 보라.
using System.Threading.Tasks;
public interface IParticipant
{
Task<bool> Prepare(TxOp op); // 자원 잠그고 찬성/반대 투표
Task Commit(TxOp op); // 반영 후 잠금 해제
Task Abort(TxOp op); // 취소 후 잠금 해제
}
public sealed class TwoPhaseCommitCoordinator
{
private readonly IParticipant _a, _b;
public TwoPhaseCommitCoordinator(IParticipant a, IParticipant b) { _a = a; _b = b; }
public async Task<bool> Execute(TxOp op)
{
bool va = await _a.Prepare(op);
bool vb = await _b.Prepare(op); // (A) 둘 다 찬성해야 진행
if (!va || !vb) { await _a.Abort(op); await _b.Abort(op); return false; }
await _a.Commit(op); // (B)
await _b.Commit(op); // (C)
return true;
}
}
public sealed class TxOp { public long ItemId; public long FromChar; public long ToChar; } 결함 코드 · C++
// 시나리오: 서로 다른 두 샤드에 있는 플레이어 간 아이템 교환을 원자적으로 처리하려고
// 2단계 커밋(2PC)을 쓴다. 코디네이터가 두 참여 샤드에 prepare 를 보내 자원을 잠그고
// 찬성을 받으면 commit 을 보낸다. 참여자는 prepare 후 코디네이터의 결정을 기다린다.
//
// 요구사항:
// - 교환은 원자적이어야 한다(양쪽 다 반영되거나 양쪽 다 취소).
// - 코디네이터/참여자가 임의 시점에 죽거나 재시작해도 자원이 영구히 잠기거나
// 한쪽만 반영되는 상태로 남으면 안 된다.
// - 잠긴 자원은 유한 시간 안에 반드시 해소되어야 한다.
//
// 과제: execute 와 참여자 흐름을 검토하고, 코디네이터/참여자가 특정 시점에 실패할 때
// 무엇이 잘못되는지, 어떤 조건에서 드러나는지, 어떻게 고칠지 설명하라. (A)(B)(C) 를 보라.
#include <cstdint>
struct TxOp { int64_t txId; int64_t itemId; int64_t fromChar; int64_t toChar; };
struct IParticipant {
virtual bool prepare(const TxOp& op) = 0; // 자원 잠그고 찬성/반대
virtual void commit(const TxOp& op) = 0; // 반영 후 잠금 해제
virtual void abort(const TxOp& op) = 0; // 취소 후 잠금 해제
virtual ~IParticipant() = default;
};
class TwoPhaseCommitCoordinator {
public:
TwoPhaseCommitCoordinator(IParticipant& a, IParticipant& b) : a_(a), b_(b) {}
bool execute(const TxOp& op) {
bool va = a_.prepare(op);
bool vb = b_.prepare(op); // (A) 둘 다 찬성해야 진행
if (!va || !vb) { a_.abort(op); b_.abort(op); return false; }
a_.commit(op); // (B)
b_.commit(op); // (C)
return true;
}
private:
IParticipant& a_;
IParticipant& b_;
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.