•
메리어트 인터내셔널같은 호텔 체인의 예약 시스템을 설계할 것이다.
•
이 장에서 다루는 내용은 다른 면접 문제에 활용될 수 있을만큼 범용성있는 것도 있다.
◦
에어비앤비 시스템 설계
◦
항공권 예약 시스템 설계
◦
영화 티켓 예매 시스템 설계
1단계: 문제 이해 및 설계 범위 확정
•
요구사항 가정
◦
시스템 규모는 5000개 호텔에 100만 개 객실을 갖춘 호텔 체인
◦
대금은 예약 시 지불한다고 가정
◦
호텔 웹사이트나 앱에서만 예약이 가능하며 취소도 가능
◦
10% 초과 예약이 가능해야 한다. 실제 객실 수보다 더 많은 객실을 판매할 수 있어야 함
◦
객실 가격은 유동적, 가격은 객실의 여유도에 따라 달라짐
비기능 요구사항
•
높은 수준의 동시성 지원
◦
성수기, 대규모 이벤트 기간에는 일부 인기 호텔의 특정 객실을 예약하려는 고객이 몰릴 수 있다.
•
적절한 지연 시간
◦
사용자가 예약을 할 때는 응답 시간이 빠르면 이상적이겠으나 예약 요청 처리에 몇 초 정도가 소요되는 것은 괜찮다.
개략적 규모 추정
•
총 5,000개 호텔에 100만 개의 객실
•
평균적으로 객실의 70%가 사용 중이고 평균 투숙 기간은 3일이라고 가정
•
일일 예상 예약 건수는 100만 * 0.7 / 3이므로 대략 240,000
•
초당 예약 건수는 240,000 / 100,000 대략 3이므로 초당 예약 트랜잭션 수는 그렇게 크지 않음
•
시스템 내 모든 페이지의 QPS는 다음과 같다. 각 단계별로 대략 90%는 이탈한다고 가정해보자.
◦
호텔/객실 상세 페이지 300
◦
예약 상세 페이지 30
◦
객실 예약 페이지 3
2단계: 개략적 설계안 제시 및 동의 구하기
API 설계
•
호텔 관련 API
◦
호텔 상세 정보 반환, 신규 호텔 추가, 호텔 정보 갱신, 호텔 정보 삭제
•
객실 관련 API
◦
객실 상세 정보 반환, 신규 객실 추가, 객실 정보 갱신, 객실 정보 삭제
•
예약 관련 API
◦
예약 이력 반환, 특정 예약 상세 정보 반환, 신규 예약, 예약 취소
데이터 모델
•
호텔 예약 시스템은 다음 질의를 지원해야 한다.
◦
호텔 상세 정보 확인
◦
지정된 날짜 범위에 사용 가능한 객실 유형 확인
◦
예약 정보 기록
◦
예약 내역 또는 과거 예약 이력 정보 조회
•
본 설계안에서는 관계형 데이터베이스를 선택했는데 그 이유는 다음과 같다.
◦
읽기 빈도가 쓰기 빈도 대비 높은 작업 흐름을 잘 지원한다.
◦
관계형 데이터베이스는 ACID 속성을 보장한다. 이는 예약 시스템을 만들 때 중요하다.
◦
관계형 데이터베이스를 사용하면 데이터를 쉽게 모델링할 수 있다.
개략적 설계안
•
이 호텔 예약 시스템은 MSA를 사용한다. 공개 API 게이트웨이가 각 서비스에 대한 요청으로 분기시켜줄 것이다.
3단계: 상세 설계
동시성 문제
•
같은 사용자가 예약 버튼을 여러 번 누를 수 있다.
◦
클라이언트 측 구현
▪
클라이언트가 요청을 전송하고 난 후, 예약 버튼을 회색으로 표시하거나 비활성화하는 것이다.
◦
멱등 API
▪
예약 API 요청에 멱등 키를 추가하는 방안이다. 예약의 ID를 멱등 키로 사용하여 방지하는 것이다.
▪
예약화면에 들어오는 경우, ID를 발급하여 해당 ID를 토대로 중복이 발생하지 않도록하는 것이다.
•
여러 사용자가 같은 객실을 동시에 예약하려 한다.
◦
비관적 락
▪
특정 트랜잭션이 특정 레코드를 변경하려할 때, 해당 레코드에 락을 걸어 접근을 방지하는 것이다.
▪
구현이 쉽고 모든 갱신 연산을 직렬화하여 충돌을 막는데, 이는 여러 레코드에 락을 거는 경우 교착 상태가 발생할 우려가 있어
◦
낙관적 락
▪
일반적으로 버전 번호와 타임스탬프 두 방법으로 구현되는 락이다. 보통은 시간 흐름에 영향을 받는 타임스탬프 대신 버전 번호를 더 자주 쓴다.
▪
데이터를 읽을 때, 버전 번호를 같이 읽고 갱신 시 읽었던 버전 번호와 다르면 갱신 요청이 실패하는 방식의 동작 방식이다.
▪
이 방법은 데이터에 대한 경쟁이 치열한 경우의 성능 저하를 제외하고서는 꽤 괜찮은 성능을 보인다.
◦
데이터베이스 제약 조건
▪
데이터베이스 내부의 제약 조건을 사용해 데이터 갱신 시, 해당 제약 조건을 검사하는 방식이다.
▪
데이터베이스의 타입에 영향을 많이 받으며 데이터에 대한 경쟁이 심한 경우, 실패하는 경우가 잦아 좋지 않은 사용자 경험을 제공할 수 있다.
시스템 규모 확장
•
호텔 예약 시스템에 대한 부하는 일반적으로 높지 않으나 야놀자, 여기어때와 같이 유명한 예약 애플리케이션과 연동되어야 할때, 평균 QPS가 증가할 수 있다.
•
먼저 모든 서비스는 무상태 서비스이므로 서버를 추가하는 것으로 성능 문제를 해결할 수는 있으나 데이터베이스는 단순히 서버를 늘리는 것만으로는 문제를 해결할 수 없다.
•
먼저 샤딩을 고민해볼 수 있다. 샤딩을 하려면 데이터를 어떻게 분배할지 정해야 하는데, hotelId가 좋은 후보가 되어줄 수 있다.
•
그리고 캐시를 고려해볼 수 있다. 잔여 객실 데이터의 경우, 과거의 정보는 필요하지 않다. 따라서 캐시를 적용해 잔여 객실을 빠르게 제공해줄 수 있다.
4단계: 마무리
•
비관적, 낙관적 락 등을 이용한 경쟁 조건 시나리오의 해결법을 알아보며 예약 시스템을 설계했다.
•
추가적으로 마이크로서비스 아키텍처에서 발생할 가능성이 높은 데이터 일관성 이슈를 더 살펴보면 좋을 것이다.