+42

Thiết Kế Hệ Thống Bán Vé (Ticketing System Design)

Đặt Vấn Đề

Những concert của Hà Anh Tuấn hay thậm chí concert của The Weeknd thu hút được rất rất nhiều khách giản trong nước và quốc tế. Tại thời điểm mở bán vé, hệ thống phải đương đầu với một số thử thách sau:

  • Lượng truy cập rất lớn trong suốt vài tiếng cao điểm
  • Một lượng rất lớn request kiểm tra số lượng vé còn lại và thông tin, trạng thái của order
  • Người thật thì ít mà bot thì nhiều

Hiểu Vấn Đề

Yêu Cầu Tính Năng

Một số chức năng chính:

  1. Kiểm tra số lượng vé còn lại
  2. Tạo order đặt vé
  3. Thanh toán order

Yêu Cầu Phi Tính Năng

Một số tính chất chính của hệ thống:

  1. Hiệu năng cao (Performance)
  2. Với lượng tải rất lớn, hệ thống có thể bị sập nhưng phải có khả năng phục hồi và phục hồi nhanh (Recoverability)
  3. Độ tin cậy cao (Reliability) nếu hệ thống lỗi, không gây ảnh hưởng nhiều về mặt con số và tài chính

Phạm Vi Thiết Kế

Hệ thống bán vé có rất nhiều vấn đề cần được giải quyết. Mình xin phép thiết kế vội, chỉ ra vấn đề và hướng giải quyết ở phần thiết kế để anh em tham khảo.

Để đơn giản, hệ thống mình thiết kế phục vụ bán vé trong nước, cần điều chỉnh thêm mới đáp ứng được yêu cầu bán vé trên toàn cầu.

Thiết Kế Tổng Quát

ticketing-system.drawio.png

Tách biệt request đọc và ghi giúp hệ thống linh hoạt, scale phần đọc và ghi một cách độc lập. Remaining Ticket Query, Order Query là 2 service đọc, hứng request từ phía client và đọc vào cache trước để tăng performance. Còn Order Taker là service ghi được tách ra từ Order Service, dùng để hứng và validate request order mua vé trước khi đẩy vào 1 topic Kafka.

Tại sao lại bắn Order Requests vào topic Kafka? Ở đây, thiết kế triển khai Event Source pattern giúp xử lý request một cách bất đầu bộ. Kafka lưu (persist) message xuống ổ đĩa, khi Order Processer down và restart lại thì có thể đọc lại message từ thời điểm bị lỗi. Ngoài ra, Nó như một lớp buffer, bước đệm trước khi tới Order Processer giúp cho hệ thống chạy ổn định. Hơn thế nữa, thứ tự order trong hệ thống bán vé rất quan trọng, nó dùng để tính số vé còn lại. Mà trong 1 partition, các message có thứ tự (offset). Anh em có thể tận dùng tính chất này của Kafka Partition.

Chặn bots. Những sự kiện hot là miếng bánh ngon của các đội fraudster, cheater. Bọn này dùng bot để có thể mua vé với số lượng lớn, rồi bán lại ăn giá chênh lệch. Trên thực tế, có tới 90-95% lượng traffic tại thời điểm mở bán vé là bots. Chặn bot là 1 topic rộng, mình có discuss thêm ở phần dưới.

Về mặt vận hành, anh em nên deploy các service lên cloud giúp scale một cách linh hoạt. Để đáp ứng được lượng tải tăng đột biến tại thời điểm bán vé, anh em cần tăng băng thông (network bandwidth) trước đó. Ngoài ra, cần có dữ liệu load test, stress test để lên kịch bản deploy hợp lý từ trước. Kịch bản ở đây đơn giản là dạng key-value, với lượng traffic X cần Y instance của Order Taker. Ở đây traffic metric sẽ được đẩy về Prometheus, con AutoScaler liên tục kiểm tra metric và dựa vào kịch bản lưu ở dưới DB để tự động đưa ra lệnh scale cho hệ thống.

Thanh toán thì anh em tích hợp với 1 Payment Service Provider (PSP), ví dụ ở đây là Stripe cho đơn giản. Nói đến thanh toán thì cũng cần đề cập tới Refund và Reconcile, nhưng 2 topic này không nằm trong phạm vi bài viết. Mình sẽ trao đổi ở 1 bài viết khác ha.

Thiết Kế Chi Tiết

Ở đầu Order Processer phải đảm bảo được thứ tự order để tính số lượng ticket còn lại. Một cơ chế mà anh em rất hay dùng để đảm bảo tính tuần tự, đó là lock. Mà lock dưới DB rất tốn kém, nó sẽ kéo performance xuống khi có nhiều request đồng thời. Có một cách tiếp cận khác, thứ tự của order trong single partition (queue) của Kafka được đảm bảo và persist, từ đó anh em có thể sử dụng single thread (để đảm bảo tính tuần tự) lấy order từ queue đó và xử lý lưu dữ liệu ngay trêm memory và định kỳ lưu những thay đổi (snapshot, batch) xuống DB. Trong snapshot có lưu kèm offset để khi xảy ra lỗi hệ thống, anh em có thể replay lại parition Kafka từ offset đã lưu.

Để phát hiện (detect), chặn (prevent) bots, anh em có thể kết hợp một số kỹ thuật sau tùy thuộc vào business của anh em:

  • Session Key
  • Check timestamp
  • Thêm challenge
  • Thêm idenponent key
  • Captcha
  • Theo dõi traffic của IP nguồn
  • Đối với mobile app, có thể thu thập thông tin device, check xem có root, debug, virtual space ko?

Lên nhiều kịch bản cho trường hợp khẩn cấp. Do hệ thống thiết kế dựa trên xử lý bất đồng bộ, tính toán trên memory và lượng tải lớn nên ta cần chuẩn bị những phương án chịu lỗi tốt. Ví dụ, chạy nhiều instance Order Processer cùng lúc, nhưng chỉ có output của 1 instance có hiệu lực. Nếu 1 live-instance bị down thì instance khác sẽ thế chỗ.

Để đáp ứng được yêu cầu bán vé trên toàn cầu, anh em cần nhiều data center đặt ở các thành phố lớn khác nhau. Thiết kế trong có thể phải thay đổi chút. Thay vì xài Event Sourcing, anh em có thể tham khảo xài Pivotal GemFire. Khi dữ liệu phình to rồi, anh em cần 1 cái dataware house để lưu lại tất cả dữ liệu (cả hot data và old data)


📚️ Ronin Engineer: https://ronin-engineer.github.io/register-post

🏢 System Design VN: https://fb.com/groups/systemdesign.vn


Tham Khảo


Nếu anh em thấy hay thì cho mình xin 1 một upvote và 1 share nhé

Cám ơn anh em rất nhiều 🙏

Facebook: https://fb.com/groups/systemdesign.vn

Discord: https://discord.gg/SyekpYxdzz

Nhóm đang tuyển writer và graphic designer nếu anh em có hứng thú thì comment ở dưới giúp mình nhé. Khi tham gia anh em có quyền lợi sau:

  • Trau dồi kỹ năng viết, kỹ năng chuyên môn
  • Được chia sẻ tài liệu nghiên cứu
  • Kết nối, học hỏi từ anh em trong nhóm

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí