# 탄력적 트랜잭션 구축: 멱등 작업 실전 적용
멱등 작업과 상태 로그를 활용한 다단계 트랜잭션은 장애 발생 시 데이터 무결성을 보장합니다. 이 방법은 MongoDB를 포함한 모든 데이터베이스에서 작동하며, 정전이나 시스템 다운으로 인한 데이터 손실을 방지합니다.
다단계 트랜잭션 작동 원리
트랜잭션을 순차적 단계로 나누고, 각 단계를 별도의 TRANSACTIONS 테이블에 로그로 기록합니다. 주요 상태:
- blocking — 동시 작업 방지를 위한 계좌 잠금.
- save_balance — 원본 잔고를 로그에 스냅샷 저장.
- main — 실제 자금 이체 실행.
- unlock — 완료 후 계좌 잠금 해제.
- finished — 성공한 트랜잭션의 최종 상태.
멱등성은 장애 후 단계를 반복해도 데이터가 손상되지 않도록 합니다. 예를 들어, A := B + 1은 멱등이지만 A := A + 1은 아니지만, 이를 두 개의 멱등 단계로 분해할 수 있습니다.
코드 예시를 통한 구현 단계
Assange 계좌에서 Agent Y 계좌로 250달러를 이체한다고 가정합니다. ACCOUNTS 테이블 초기 데이터:
| ID | NAME | BALANCE | TR_ID |
|----|----------|---------|-------|
| 34 | Assange | 300 | null |
| 78 | Agent Y | 7 | null |
1. 계좌 잠금 (STATUS='blocking')
먼저 TRANSACTIONS 레코드 생성:
| ID | FROM_ID | TO_ID | AMOUNT | FROM_BALANCE | TO_BALANCE | STATUS |
|----|---------|-------|--------|--------------|------------|----------|
| 172| 34 | 78 | 250 | null | null | blocking |
MongoDB에서 원자적 명령으로 잠금:
db.accounts.updateOne(
{ ID: 34, TR_ID: null },
{ $set: { TR_ID: 172 } }
);
문서가 업데이트되지 않으면 잠금 실패—재시도 또는 중단. 데드락 방지를 위해 ID를 미리 정렬합니다.
2. 잔고 스냅샷 저장 (STATUS='save_balance')
잠금 후 원본 잔고를 TRANSACTIONS에 복사—설계상 멱등:
db.transactions.updateOne(
{ ID: 172 },
{ $set: { FROM_BALANCE: 300, TO_BALANCE: 7, STATUS: 'save_balance' } }
);
3. 이체 실행 (STATUS='main')
저장된 잔고를 활용한 핵심 작업:
db.accounts.updateOne(
{ ID: 34, TR_ID: 172 },
{ $set: { BALANCE: 50 } } // 300 - 250
);
db.accounts.updateOne(
{ ID: 78, TR_ID: 172 },
{ $set: { BALANCE: 257 } } // 7 + 250
);
변경 적용 후 상태를 'unlock'으로 업데이트.
4. 잠금 해제 및 완료 (STATUS='unlock')
TR_ID 확인 후 잠금 해제:
db.accounts.updateOne(
{ ID: 34, TR_ID: 172 },
{ $set: { TR_ID: null } }
);
두 계좌 잠금 해제 후 상태를 'finished'로 설정.
장점과 한계
주요 장점:
- 장애 내성: 데이터 손실 없이 모든 장애 복구.
- 멱등성: 분산 시스템에서 안전한 재시도 필수.
- 범용성: MongoDB 외 모든 DB 적용 가능.
- 일관성: 모든 단계에서 데이터 무결성 유지.
- 성능: 추가 로그로 약간의 속도 저하.
단점은 복잡도 증가와 로그 오버헤드입니다. 금융 앱이나 핵심 시스템에는 가치 있습니다.
개발자 팁
- DB의 원자 연산 활용해 잠금/업데이트.
- 잠금 실패 시 재시도 로직 구축.
- 프로세스 갑작스런 종료 등 크래시 시나리오 테스트.
- ID 정렬로 데드락 위험 최소화.
NoSQL 유연성과 2PC 수준 신뢰성을 제공합니다.
— Editorial Team
아직 댓글이 없습니다.