성능은 모르겠고 동시성 이슈는 확실히 보장 된 것 같다.
낙관적 락은 적용할 필요가 없어 보인다.
낙관적 락은 같은 엔터티를 수정할 때 보통 쓰인다. 동시에 수정을 요청했을 때 막도록, @Version은 같은 엔터티를 수정하는 경우 ~~ 해서 동시성 문제를 방어한다.
하지만 여행 예약은 예약하기를 누를 때마다 각각 다른 엔터티를 생성한다. -> checkin, checkout id 금액 각각 다 다르다.
엔터티마다 @Version의 변수가 각각 생성되므로 낙관적 락은 사용할 수 없다.
요약하자면 프론트엔드에서 예약 가능한 날짜를 받고, 예약 서비스를 호출하면 항상 새로은 Trip 엔터티를 생성하고 요청할 것이다. 그럼 우리는 새로운 Trip이 기존의 Trip들과 날짜가 겹치는지 안 겹치는지만 확인하면 되는 것 아닌가?
그러면 예약할 때 계속 한 스레드에서 Trip이 DB에 저장이 완료 될 때까지 기다릴 필요가 있을까? 대기 Queue(Event Queue)를 사용해 보자
Event Queue를 통해서 숙소 예약
이제 우리는 여행 예약 서비스를 호출하면 Event Queue를 통해서 숙소 예약을 진행 할 것이다.
사용자가 예약을 누른다면 예약 서비스가 호출되고 예약이 날라갈 것이다.
예약은 Event Queue에 차곡차곡 쌓이면서 처리될 것이고 사용자는 처리되는 동안 여행 정보 창에서 대기를 한다.
Event Queue의 로직을 실행하다가 에러가 발생하면 Rollback 후 예외를 발생시킨다.
그러면 중복되는 날짜가 있고 에러를 발생시키려면 어떻게 해야 할까? 생각을 바꿔보자. 만약 DB에 생성 쿼리를 날리고 DB에서 중복 확인 작업을 거치면 가능해질까?
여행을 생성할 때 중복되는 날짜가 있는지 체크하는 트리거를 작성하고 INSERT 할 때마다 트리거를 호출 해 주면 될 것 같다.
다음과 같이 트리거를 하면 중복 날짜가 있는 지 확인할 것이고 만약 있다면 에러를 발생시킬 것이다.
이 예약이 실패하면 예외처리로 보내주자
# Event Queue를 사용한 Flow(예상)
- 사용자가 예약을 요청
- 컨트롤러가 예약 정보를 받음
- 요청의 유효성 검증
- STANDBY의 유효한 예약정보 생성
- 예약정보를 데이터베이스에 저장
- 이벤트 퍼블리셔가 예약정보 이벤트를 퍼블리싱
- 사용자에게 예약정보에 대한 응답을 보내고 Http 통신을 종료
- 발생된 예약 정보 이벤트를 이벤트 리스너가 감지하고 예약정보 이벤트에서 결제 거래 정보를 추출
- 큐가 꽉 차 있지 않다면 예약정보를 큐에 입력하고 예약정보 상태를 QUEUE로 데이터베이스 업데이트
- 큐가 꽉 차 있다면 상태를 QUEUE_WAIT로 데이터베이스 업데이트
- 백그라운드 스레드에서는 큐에 있는 예약 정보들을 처리하고 상태를 SUCCESS 혹은 FAILURE로 업데이트
- 예약 완료에 대한 후처리를 진행(ex. 예약 결과를 메일로 전송 or 예약 실패 결과를 메일로 전송)
Java에서 검증 시 예상 flow

Trigger 사용 시 예상 flow

