매장 예약 서비스 - 동시성 문제
매장 예약 서비스를 개발하면서 중요하다고 생각한 제약사항 중 하나는 예약 가능 여부가 중요하다고 생각했었다 그래서 해당 매장에서 예약 하려는 시간대의 남아있는 테이블 수를 계산해 예약 가능 여부를 체크했었다 하지만 문제는 동시에 예약 요청이 들어오는 경우는 전혀 생각하지 않았었다..
동시성 문제
두개의 요청 중 하나의 요청만 예약 가능하다고 할때 매장에다 동시에 예약 요청을 보내게 되면 둘다 예약에 성공한다
예시로 총 테이블 6개를 보유한 매장이 있다 예약 하려는 시간대에 이미 5개의 테이블이 예약되어 있는 상황 즉 테이블 1개만 예약 가능한 상황이다 1개의 테이블 예약 요청을 동시에(같은 시간대에) 보내게 되면 첫번째 요청은 성공해야하고 두번째 요청을 실패해야 하지만 둘다 예약에 성공한다
이런일은 발생하면 안된다고 생각했다..
S_IDX : 매장 고유번호
START_TIME : 예약 요청 시간
RESER_TIME : 예약한 시간
TABLE_CNT : 예약 한 테이블 수
RESER_STAT : 예약 상태
해결 방법 - 비관적 락 ( 배타 락 )
공유 락 설정
처음에는 비관적 락인 공유 락을 설정 했었다 그랬더니 공유 락은 다른 트랜잭션에서 쓰기는 불가능하지만 읽기는 가능하므로 동시에 조회하게 되어 예약 가능한 테이블의 수가 같게 나와버린다 이렇게 되버리면 예약 가능 여부 체크가 정상적으로 동작하지 못하게 된다
그리고 서로 공유 락을 획득한 상황에서 저장을 위해 배타 락을 획득하려고 하지만 공유 락이 걸려 있어 서로 락이 해제 될때까지 무한정 대기하는 데드락 현상이 발생했었다
successReserTableCnt : 예약상태가 성공처리된 테이블 수 (해당 시간대에 이미 예약이 되어있는 테이블 수)
reservationTableCnt : 예약 요청한 테이블 수
storeTableCnt : 매장이 보유한 테이블 수
배타 락 설정
그래서 배타 락으로 설정하게 되었다 배타 락은 다른 트랜잭션에서 읽기도 불가능 하기 때문에 예약 가능한 테이블의 수가 다르게 나온다 따라서 예약 가능 체크가 정상적으로 동작할 수 있었다
이렇게 해서 예약 시스템의 동시성 이슈도 해결 하였다
참고링크
https://isntyet.github.io/jpa/JPA-%EB%B9%84%EA%B4%80%EC%A0%81-%EC%9E%A0%EA%B8%88(Pessimistic-Lock)/
https://unluckyjung.github.io/db/2022/03/07/Optimistic-vs-Pessimistic-Lock/
https://ksh-coding.tistory.com/121
https://studyhardd.tistory.com/86
https://hudi.blog/mysql-8.0-shared-lock-and-exclusive-lock/
https://parkjeongwoong.github.io/articles/Failure/5