재고를 예약한 이후, 서버 장애 등의 이유로 예약된 재고 정보가 소실되는 경우, 실제 재고는 있는데 DB 상에는 없는 경우가 발생한다.
현재 결제 처리 흐름은 다음과 같다.
// 결제 처리 로직
try {
reservedLines = reserveOrderStocks(order); // 재고 예약
tossPaymentClient.confirm(...); // 결제 진행
// 성공
payment.complete();
order.complete();
} catch (...) {
// 실패
restoreReservedStocks(reservedLines); // 재고 복구
}
하지만 서버 장애로 인해 재고 예약 이후 서버 실행이 중단된다면, catch 문이 실행되지 못하여 재고 손실이 발생하게 된다.
try {
reservedLines = reserveOrderStocks(order); // 재고 예약
// 💥 예상치 못한 이유로 로직 중단
tossPaymentClient.confirm(...); // 결제 진행
// 성공
payment.complete();
order.complete();
} catch (...) {
// 실패
restoreReservedStocks(reservedLines); // 재고 복구
}
이로 인해 다음과 같은 영향이 발생한다.
따라서 위 문제를 해결할 필요가 있었다.