Final Project: Ticket Booking Platform

4 câu hỏi~30 phútTừ khóa: microservices, milestone, acceptance criteria, failure simulation, benchmark, trade-off, game day

Học xong rồi, giờ mình muốn tự code một project để kiểm tra toàn bộ kiến thức. Làm gì nhỉ?

Làm Ticket Booking Platform: hệ thống đặt vé sự kiện, Java/Spring Boot, microservices. Đây không phải tutorial CRUD. Đây là bài thi cuối: bạn tự code, AI chỉ ra đề, review và phỏng vấn.

1. Vì sao chọn đặt vé?

Vì bài toán này chạm gần như mọi chương đã học:

Nó chính là bài Ticket booking và Flash sale của chương System Design, ghép với chương Distributed. Lần này bạn code thật, làm hỏng thật, đo thật.

2. Nguyên tắc

problem → design → implementation → failure simulation
        → benchmark → trade-offs → interview review

Mỗi milestone sẽ có: đề bài, acceptance criteria, test cases, failure scenarios, checklist.

3. Kiến trúc

                 Postman / k6 / integration test
                              │
                    ┌─────────▼─────────┐      ┌──────────┐
                    │  gateway          │─────▶│ Keycloak │ (JWT)
                    │  SC Gateway       │      └──────────┘
                    │  JWT + rate limit │── Redis
                    └──┬──────────┬─────┘
                       │          │
              ┌────────▼───┐  ┌───▼────────┐   REST    ┌──────────────┐
              │ catalog    │  │ booking    │──────────▶│ payment      │
              │ events,    │  │ hold seat, │◀─ webhook │ mock PSP +   │
              │ seats,cache│  │ confirm,   │           │ fault inject │
              └──┬─────┬───┘  │ saga       │           └──────┬───────┘
                 │     │      └──┬─────┬───┘                  │
             Postgres Redis   Postgres │ outbox ─▶ Kafka ◀─────┘
                                       │
                                  ┌────▼──────────┐
                                  │ notification  │◀── RabbitMQ
                                  │ consumer, DLQ │   (quorum queue)
                                  └───────────────┘

  Toxiproxy chen giữa các kết nối để giả lập lỗi mạng.
  Prometheus + Grafana + OTel quan sát toàn bộ.
ServiceTrách nhiệmCông nghệ chính
gatewayEntry point, validate JWT, rate limitSpring Cloud Gateway, Keycloak, Redis
catalogSự kiện, sơ đồ ghế, đọc nhiềuPostgres, Caffeine + Redis cache
bookingGiữ ghế, xác nhận, điều phối sagaPostgres, Redis, Kafka, Outbox
paymentMock PSP: chậm, lỗi, UNKNOWN, webhookPostgres, idempotency key, fault injection API
notificationGửi email/SMS giảRabbitMQ consumer, DLQ, priority

Hạ tầng (docker-compose): Postgres, Redis, Kafka, RabbitMQ, Keycloak, Toxiproxy, Prometheus, Grafana. Test: JUnit 5, Testcontainers, k6.

4. 12 milestone

#Mục tiêuÔn lạiKiến thức mớiXong khi
M0Requirements, capacity, dựng hạ tầngFramework, SLO & capacitydocker-compose đủ infra, skeleton 5 serviceCó tài liệu FR/NFR + ước lượng QPS; docker compose up xanh; health check 5 service OK
M1Chống bán trùng ghếRace condition, DB locks, Redis lock5 cách: synchronized → atomic UPDATE → FOR UPDATE → @Version → Redis SET NXTest 1000 request đồng thời vào 1 ghế: đúng 1 thành công; bảng benchmark cả 5 cách; chứng minh synchronized hỏng khi chạy 2 instance
M2Hold + expiryTicket bookingState machine HELD → CONFIRMED / EXPIRED, job quét hết hạn với ShedLockGhế tự nhả sau TTL; 2 instance job không xử lý trùng; chuyển trạng thái sai bị từ chối
M3Thanh toán an toànPayment, Timeout & retryIdempotency key, trạng thái UNKNOWN, webhook, reconciliation jobGửi lại cùng key không trừ tiền 2 lần; PSP timeout → UNKNOWN → reconciliation chốt đúng
M4Lỗi dây chuyền A→B→CPartial failure, Circuit breaker, Resilience4jTimeout, retry + backoff, circuit breaker, fallback; Toxiproxy tiêm latency, cắt kết nốiPayment chậm 5s không làm booking cạn thread; dashboard thấy trạng thái circuit
M5Saga + Outbox + InboxSaga, Outbox/Inbox, Order–inventory–payment, Delivery semanticsSaga qua Kafka, outbox relay, inbox dedupe, compensationKill service giữa chừng rồi bật lại: không mất event, không xử lý trùng, ghế được nhả khi payment fail
M6NotificationNotification, Quorum queue, Retry & DLXQuorum queue, DLQ, priority, manual ackMessage lỗi vào DLQ sau N lần; email xác nhận vé được ưu tiên hơn marketing
M7Flash saleFlash sale, Rate limitingRate limit ở gateway, trừ tồn kho Redis-first (Lua), queue ghi DBk6 10k VU: không oversell, DB không quá tải, user bị chặn nhận 429 rõ ràng
M8Scale catalogCache strategies, Replication & sharding, Scale app & DBCache 2 tầng Caffeine + Redis, read replica, bài tập tư duy shardingĐo được cache hit ratio; invalidation đúng; có tài liệu chọn shard key cho bảng seat
M9Benchmark mô hình chạyMVC vs WebFlux vs VT, Virtual threadsCùng endpoint 4 kiểu: sync, async, reactive, virtual threads; k6 đo p50/p95/p99Có bảng số liệu + giải thích vì sao kết quả như vậy
M10Security + observabilityResource server + Keycloak, TracingKeycloak realm, role, resource server; OTel trace xuyên service, Grafana dashboardKhông token → 401, sai role → 403; một trace thấy đủ gateway → booking → payment → Kafka
M11High availabilityHA, Kafka replication, Sentinel, HelmKafka 3 broker, RabbitMQ cluster, Redis Sentinel, deploy K8s bằng Helm, CI pipelineKill 1 broker, kill Redis master: vẫn nhận booking; CI chạy test xanh
M12Game day + mock interviewToàn chương Distributed và System DesignSự cố ngẫu nhiên do AI ra, viết postmortemXử lý được sự cố không báo trước; trình bày lại toàn bộ thiết kế trong 45 phút phỏng vấn

5. Cấu trúc repo gợi ý

ticket-booking/
├── docker-compose.yml          # Postgres, Redis, Kafka, RabbitMQ, Keycloak,
│                               # Toxiproxy, Prometheus, Grafana
├── .env.example                # biến môi trường, không commit secret
├── gateway/
├── catalog-service/
├── booking-service/
├── payment-service/            # mock PSP + fault injection API
├── notification-service/
├── common/                     # event schema, error model (giữ nhỏ)
├── tests/
│   ├── postman/                # collection theo milestone
│   └── k6/                     # load test script
├── infra/
│   ├── keycloak/realm.json
│   ├── grafana/dashboards/
│   └── helm/
└── docs/
    ├── requirements.md         # M0
    ├── adr/                    # mỗi quyết định = 1 ADR
    ├── benchmarks/             # số liệu M1, M7, M9
    └── postmortems/            # M12

6. Thang chấm (3 mức)

MứcMô tả
ĐạtHappy path chạy đúng, acceptance criteria xanh, có integration test với Testcontainers.
KháThêm: mọi failure scenario đã chạy thử, có số liệu benchmark, có ADR giải thích trade-off.
Sẵn sàng phỏng vấn seniorThêm: giải thích được vì sao số liệu như vậy, biết giới hạn của thiết kế, trả lời được "tải x10 thì sao?" mà không cần nhìn code.

7. Definition of Done (mỗi milestone)

Mỗi milestone có trang chi tiết riêng: bắt đầu từ M0, hoặc chọn trong mục lục bên trái.

12 milestone nhiều quá, làm theo thứ tự nào?

Đúng là nhiều. Nhưng không cần làm theo số thứ tự cứng. Có một trục bắt buộc, phần còn lại là nhánh.

M0 ─▶ M1 ─▶ M2 ─▶ M3 ─▶ M4 ─▶ M5        (trục lõi: dữ liệu đúng)
                              │
            ┌─────────────────┼──────────────┐
            ▼                 ▼              ▼
           M6                M7             M10
       (notification)   (flash sale)   (security/obs)
                              │
                         M8 ─▶ M9            (hiệu năng)
                              │
                             M11 ─▶ M12      (HA + thi cuối)

Mẹo: mỗi milestone là một branch + một PR. Học buổi tối thì ước lượng 1–2 tuần/milestone.

AI hỗ trợ mình thế nào mà không làm hộ?

Bạn nắm đúng điểm quan trọng: nếu AI viết code thì project không còn kiểm tra được bạn. AI chỉ đóng 3 vai:

VaiLàm gìKhông làm
Task giverRa đề milestone, acceptance criteria, thêm failure scenario bất ngờKhông đưa code mẫu
ReviewerĐọc PR, chỉ race condition, transaction sai, thiếu testKhông sửa hộ, chỉ đặt câu hỏi và chỉ chỗ
InterviewerHỏi "vì sao chọn X", "nếu Y chết thì sao"Không cho đáp án trước khi bạn trả lời

Vòng lặp mỗi milestone:

AI ra đề ─▶ bạn design (ADR) ─▶ AI review design
   ─▶ bạn code + test ─▶ AI review PR ─▶ bạn chạy failure + benchmark
   ─▶ AI phỏng vấn ─▶ chưa đạt? quay lại bước cần sửa

Cách làm việc với agent xem lại bài Làm việc với AI agent. Quy tắc đơn giản: kẹt quá 2 giờ thì xin gợi ý, không xin lời giải.

Vậy làm xong M12 là đủ đi phỏng vấn chưa?

Gần đủ, chỉ cần chỉnh một điểm: nhà tuyển dụng không chấm project chạy được, họ chấm bạn kể lại được quyết định. Hãy chuẩn bị:

Sau đó luyện thêm với Top 100 câu hỏi.


Tự kiểm tra

Vì sao synchronized không đủ chống bán trùng ghế khi chạy 2 instance booking?

Lock chỉ có tác dụng trong một JVM. Hai instance có hai monitor riêng nên vẫn bán trùng. Cần khóa ở DB hoặc Redis.

Payment trả UNKNOWN thì booking nên làm gì?

Không coi là fail ngay. Giữ trạng thái chờ, đợi webhook hoặc chạy reconciliation, gọi lại với cùng idempotency key.

Outbox giải quyết vấn đề gì trong M5?

Dual write: ghi DB thành công nhưng gửi Kafka thất bại. Event được ghi cùng transaction với dữ liệu rồi relay sang Kafka.

Một milestone được coi là xong khi nào?

Khi đủ Definition of Done: test xanh, failure scenario đã chạy thật, có benchmark (nếu có), có ADR, qua review và phỏng vấn của AI.