設計飯店預訂系統 (Hotel Reservation)

Hard★★★★Draft

FromSystem Design Interview

Concepts practiced🛡️ 冪等設計 (Idempotency)🤝 分散式交易與兩階段提交 (Distributed Transactions & 2PC)⚡ 快取策略 (Caching Strategies)

Convention: read the requirements & constraints first, sketch your own design, then expand the reference to compare.

📚 From the Books

設計飯店預訂系統 (Hotel Reservation)ProblemHardGeo & Location

為連鎖飯店設計訂房系統。TPS 不高,難點在併發訂同一房型的競態避免重複訂房——同一套設計也適用於 Airbnb、航班與電影票訂位。

📋 Requirements

🧠 Core Ideas

TIP

使用者訂的是房型 (room type),不是特定房間——房號入住時才給。庫存以 room_type_inventory 表按「每個日期一列」建模,欄位 total_inventorytotal_reserved,複合主鍵 (hotel_id, room_type_id, date),未來 2 年的列由每日排程預先填入。

檢查可訂房:選出日期區間內的列,逐日驗證 (total_reserved + rooms) <= total_inventory;支援超賣只需改成 <= 110% * total_inventory。選關聯式資料庫:讀多寫少、業務關係穩定易建模,且 ACID 保證能避免負餘額、重複扣款、重複訂房。

⚖️ Reference Design

微服務與 API
  • microservice 架構:CDN + API Gateway(限流/認證/路由)後接 hotel、rate、reservation、payment 等服務;跨服務用 gRPC。
  • 建立訂房 POST /v1/reservationsroomTypeIDroomCountreservationID
  • reservationID 同時作為 idempotency key,避免同房型同日被重複下單。
併發:重複訂房與競態
  • 同一使用者重複點擊:靠冪等 API——reservation_id 作 reservation 表主鍵,第二次提交撞唯一性限制即失敗。(客戶端灰化按鈕不可靠。)
  • 多人搶最後一間:非 serializable 隔離下,兩交易都讀到「還有 1 間」而雙雙成功→超賣。需鎖定機制。
  • 悲觀鎖SELECT ... FOR UPDATE):序列化更新,但易 deadlock、不具擴展性——不建議
  • 樂觀鎖(version number):不鎖庫,衝突才重試;訂房 QPS 通常不高,是好選項
  • 資料庫限制CHECK(total_inventory - total_reserved >= 0)):實作最簡單,低競爭下運作良好,也是好選項。
擴展與快取
  • 服務無狀態可水平擴展;資料庫按 hotel_id 分片(多數查詢先選飯店)。
  • 只有當前與未來庫存有意義→用 Redis(TTL + LRU)做 inventory cache,key 為 hotelID_roomTypeID_{date}
  • 讀路徑走快取,但資料庫才是真實來源,訂房時仍在 DB 端重新驗證庫存;DB→cache 用非同步更新或 CDC(如 Debezium)傳播。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading