programming3 MIN READ

[시스템 디자인] 07. 호텔 예약 시스템

[시스템 디자인] 07. 호텔 예약 시스템

시스템 디자인 시리즈의 글입니다.

호텔체인예약시스템 설계. 다른 인기 면접문제에도 적용 가능

1. 문제 이해 및 설계 범위 확정

복잡한 시스템이기때문에 면접관에게 질문해서 범위를 명확히해야함

기능 요구사항

  • 호텔 정보 페이지 표시
  • 객실 정보 페이지 표시
  • 객실 예약 지원
  • 호텔 객실정보 추가/삭제/갱신 관리자페이지
  • 초과예약(10%) 지원
  • 유동적은 객실요금 지원

비기능 요구사항

  • 높은 수준의 동시성 : 성수기, 대규모이벤트 기간에 고객이 몰릴수있음
  • 적절한 지연시간 : 응답시간은 빠르면 좋지만 어느정도 지연은 ok

개략적 규모 추정

  • 총 5000개호텔, 100만개 객실
  • 일일 예상 예약건수 24만
  • 3TPS
  • 350QPS

2. 개략적 설계안

API 설계

  • 호텔관련 API
  • 객실관련 API
  • 예약관련 API

데이터 모델

시스템 규모가 크지 않고 예약에 대한 ACID 보장이 중요하므로 관계형 데이터베이스를 채택 (CQRS는 어떨까?)

  • 호텔서비스
    • hotel
    • room
  • 요금서비스
    • room_type_rate
  • 예약서비스
    • reservation
    • room_type_inventory
  • 투숙객 서비스
    • guest

개략적 설계안

msa 를 사용하여 설계

image

  • 호텔서비스 : 호탤, 객실 상세정보 제공. 정적인 데이터이므로 캐싱
  • 요금서비스 : 특정 date에 얼마의 요금을 받아야하는지
  • 예약서비스 : 예약요청을 받고 객실을 예약. 잔여객실정보 갱신.
  • 결제서비스 : 고객의 결제를 처리. 최종 예약상태 갱신.
  • 호텔 관리 서비스 : 승인된 호텔 직원만 사용가능. 관리자기능 제공.

서비스들은 각자 서로 상호작용하게됨. 필요시에는 gRPC같은 고성능 원격 프로시저 호출 프레임웍을 사용하기도함.

3. 상세설계

개선된 데이터 모델

  • 특정 ‘객실’을 예약하는게 아닌, 특정 ‘객실 유형’을 예약하는것임을 주의
  • 이를 위해 room_type_inventory 테이블을 추가
  • 타입별 특정일에 예약가능한 room의갯수를 저장
  • 데이터가 크다면, cold storage 및 shading 방식을 사용.

동시성 문제

  • 같은 사용자가 예약버튼을 여러번 누름
    • 클라측 예약버튼 비활성화를 통한 이중클릭 방지 → 우회가능
    • 멱등API 활용 → 멱등키인 reservation id를 사용해 예약
  • 여러 사용자가 같은 객실을 동시에 예약
    • 비관적 락 (비관적 동시성 제어) : 사용자가 갱신하려는 순간 락을걸어 동시 업데이트 방지. 단 여러 업데이트가 일어나면 deadlock이 일어날수있음. 교착상태가 길어지면 DB성능저하를 피할수 없음.
    • 낙관적 락 (낙관적 동시성 제어) : 여러 사용자가 동시에 자원을 갱신하는것을 허용하고, 버전번호를 검사해 유효성검사에 실패하면 롤백. 경쟁이 치열한상황에서는 1명의 사용자만 성공하고 나머지는 계속 retry를 반복해야하기때문에 권장하지 못하는 방법.
    • 데이터베이스 제약조건 : 낙관적 락과 유사하나 제약조건을 걸어 이 제약조건에 위배되면 롤백. 마찬가지로 경쟁이 치열한 상황에서의 retry 문제가 동일하게 있으므로 유의해야함.

시스템 규모 확장

  • 데이터베이스 샤딩
    • hotel_id를 키로하여 샤딩하면 좋다.
  • 캐시
    • 호텔 잔여객실의 경우 과거데이터는 필요가 없다는데서 캐시를 적용하기 매우 좋음. TTL 을 설정하여 과거데이터는 자동으로 만료시키면 효율적으로 데이터를 서비스할 수있다. 다만, DB와의 일관성 문제를 계속 염두에 두어야한다.
    • DB갱신시 캐시데이터를 갱신하여 일관성을 유지하도록한다.
    • Debezium 같은 CDC 솔루션을 사용하는 방법도 있다.
  • 서비스간 데이터 일관성
    • 순수msa주의자들은 각 서비스별로 독자 DB를 사용한다고 주장할수도 있음.
    • 이번 설계에서는 예약서비스가 잔여객실테이블과 예약테이블을 모두 사용함.
    • 꼭 분리해야한다면 2PC, Saga같은 일관성 해결법칙을 쓰는것도 방법임.
    • 다만 이러한 일관성 해결을 위해 설계가 지나치게 복잡해질수있음.