Skip to content

🎯 Mục tiêu

🎯 Sau bài này bạn sẽ nắm được:

  • Theo dõi được vòng đời hoàn chỉnh của một request từ trình duyệt đến database và ngược lại
  • Nhận diện mỗi building block Phase 1 đang hoạt động ở đâu trong kiến trúc
  • So sánh kiến trúc 4 hệ thống thực tế và hiểu tại sao mỗi hệ thống ưu tiên building blocks khác nhau
  • Sẵn sàng cho Phase 2: Case Studies

Capstone — Khi các building blocks kết hợp trong hệ thống thực

Bạn đã học từng mảnh ghép riêng lẻ: DNS, TCP/UDP, HTTP, Load Balancing, Caching, Database Scaling. Giống như học từng nốt nhạc — bây giờ là lúc chơi cả bản nhạc.

Khi một người dùng ở TP. Hồ Chí Minh mở Instagram trên điện thoại và lướt news feed, chiếc điện thoại đó thực thi một choreography liên quan đến mọi building block bạn đã học. Từ ngón tay chạm màn hình đến byte cuối cùng rời khỏi database — mỗi bước đều là một bài học bạn đã đi qua. Capstone này sẽ theo dõi hành trình đó từ đầu đến cuối, cho bạn thấy tất cả các mảnh ghép khớp với nhau như thế nào.

Đây không phải bài học thêm kiến thức mới. Đây là bài kiểm chứng: nếu bạn thực sự hiểu từng building block, bạn sẽ đọc xong chương này mà cảm thấy mọi thứ "click" vào đúng vị trí. Nếu có chỗ nào còn mờ — quay lại bài tương ứng, đọc lại, rồi trở về đây.


Vòng đời hoàn chỉnh của một request

Hãy theo dõi chính xác những gì xảy ra khi một người dùng gõ https://instagram.com/feed vào trình duyệt và nhấn Enter. Mỗi bước sẽ tham chiếu ngược về bài Phase 1 tương ứng.

Bước 1: DNS Resolution

📚 Xem chi tiết: DNS Resolution

Trình duyệt cần biến domain instagram.com thành một địa chỉ IP cụ thể. Hành trình bắt đầu từ browser cache — nếu bạn vừa truy cập Instagram 30 giây trước, trình duyệt đã lưu IP rồi. Cache miss? Hỏi OS cache. Vẫn miss? Request được gửi đến recursive resolver (thường là DNS của ISP như VNPT hoặc Viettel), rồi từ đó đi đến root NS → TLD NS (.com) → authoritative NS của Instagram.

Điểm mấu chốt cho hệ thống lớn: Instagram sử dụng GeoDNS. Với người dùng ở Việt Nam, authoritative nameserver trả về IP của edge server gần nhất — có thể là Singapore hoặc Hong Kong, không phải California. Điều này cắt giảm hàng trăm millisecond latency.

TTL được set 60 giây — cực thấp. Lý do: nếu edge server Singapore gặp sự cố, Instagram cần failover sang server khác trong vòng 1 phút. TTL cao (24h) đồng nghĩa người dùng bị kẹt ở server chết suốt 24 giờ.

Bước 2: TCP Handshake + TLS

📚 Xem chi tiết: TCP vs UDP

Có IP rồi, trình duyệt mở TCP connection đến edge server. Ba bước kinh điển: SYN → SYN-ACK → ACK — mất 1 RTT (Round Trip Time). Từ TP.HCM đến Singapore, RTT khoảng 30-40ms, tức TCP handshake tốn ~35ms.

Nhưng chưa xong — URL bắt đầu bằng https://, nên cần TLS handshake để mã hóa kết nối. TLS 1.3 tối ưu hơn phiên bản cũ: chỉ cần thêm 1 RTT (thay vì 2 RTT của TLS 1.2). Nếu người dùng từng kết nối trước đó, TLS 1.3 hỗ trợ 0-RTT resumption — gửi dữ liệu ngay trong ClientHello, không cần đợi.

Tổng chi phí setup: 2-3 RTT trước khi trình duyệt gửi được byte dữ liệu đầu tiên. Với RTT 35ms đến Singapore, đó là 70-105ms chỉ để "bắt tay". Đây là lý do connection reuse quan trọng đến vậy.

Bước 3: HTTP/2 Request

📚 Xem chi tiết: HTTP Evolution

Kết nối đã thiết lập, trình duyệt gửi GET /feed qua HTTP/2. Không giống HTTP/1.1 cần mở nhiều TCP connection cho nhiều resource, HTTP/2 multiplex mọi thứ trên cùng một connection — request feed, ảnh avatar, CSS, JavaScript đều chạy song song trên các stream khác nhau.

Headers được nén bằng HPACK: auth token (Bearer JWT), cookies, User-Agent, Accept-Language... thay vì gửi raw text ~800 bytes mỗi request, HPACK nén xuống còn ~50 bytes bằng static/dynamic table. Với hàng chục request concurrent, tiết kiệm đáng kể.

HTTP/2 còn cho phép server push — server có thể chủ động gửi CSS và JavaScript bundle mà nó biết trình duyệt sẽ cần, trước cả khi trình duyệt parse HTML và tạo request. Mỗi millisecond tiết kiệm ở đây nhân lên cho hàng tỷ request mỗi ngày.

Bước 4: L4 Load Balancer

📚 Xem chi tiết: Load Balancing

Request đến edge datacenter và gặp L4 Load Balancer đầu tiên — thường là NLB (Network Load Balancer) hoặc IPVS (IP Virtual Server). L4 LB hoạt động ở tầng Transport: nó chỉ nhìn thấy IP và port, không quan tâm nội dung HTTP bên trong.

Tại sao cần L4 riêng? Tốc độ. L4 LB xử lý hàng triệu connection/giây vì nó không cần parse HTTP. Nhiệm vụ duy nhất: nhận TCP connection và route đến một trong nhiều L7 LB instance phía sau, thường dùng ECMP (Equal-Cost Multi-Path) hoặc Maglev hashing.

Health check chạy liên tục: L4 LB gửi TCP SYN probe đến mỗi L7 LB mỗi 5 giây. L7 instance nào không respond trong 3 lần liên tiếp bị loại khỏi pool. Khi instance recover, nó được thêm lại tự động — zero manual intervention.

Bước 5: L7 Load Balancer / Reverse Proxy

📚 Xem chi tiết: Load Balancing

L7 Load Balancer — chạy Nginx, Envoy, hoặc custom proxy — là nơi TLS termination thực sự xảy ra. TCP connection từ trình duyệt được decrypt ở đây, và từ L7 LB trở đi, traffic bên trong datacenter thường chạy plaintext (hoặc mTLS giữa các service).

L7 LB đọc HTTP headers và đưa ra routing decision thông minh: request đến /feed được route đến Feed Service cluster, /stories đến Stories Service, /api/v1/users đến User Service. Đây là content-based routing — khả năng mà L4 LB không có vì nó không parse HTTP.

Một hành động quan trọng: L7 LB inject X-Request-ID (UUID) vào mỗi request. Header này theo request suốt hành trình qua mọi service, giúp engineer trace được chính xác đường đi khi debug production incident lúc 3 giờ sáng.

Bước 6: Application Server + Cache Check

📚 Xem chi tiết: Caching

Feed Service nhận request và câu hỏi đầu tiên luôn là: "User X đã có pre-computed feed trong cache chưa?" Service kiểm tra Redis — in-memory cache với latency ~1ms.

Cache HIT: Redis trả về feed đã pre-compute (danh sách post IDs + metadata). Tổng thời gian từ application server đến response: ~2ms. Request quay về ngay, không cần chạm database. Với hệ thống lớn, 95%+ request kết thúc tại bước này — đó là sức mạnh của caching.

Cache MISS: User mới, hoặc cache vừa expire (TTL 60 giây), hoặc có bài post mới invalidate cache. Service phải xuống database để build feed từ đầu. Thời gian: 50-200ms — gấp 25-100 lần so với cache hit. Đây là lý do cache hit ratio quan trọng sống còn: 1% cache miss rate thêm vào = hàng nghìn request/giây đổ xuống database.

Bước 7: Database Query

📚 Xem chi tiết: Database Design

Cache miss → phải query database. Instagram không dùng một database đơn lẻ — đó sẽ là single point of failure và bottleneck ngay lập tức.

Query 1 — PostgreSQL (sharded by user_id): Lấy danh sách người dùng mà user X follow. Shard key là user_id, nên query chỉ hit đúng 1 shard — không cần scatter-gather across toàn bộ cluster. Đây là lợi ích của shard key design tốt.

Query 2 — Cassandra (time-series optimized): Lấy recent posts từ các user trong following list. Cassandra được chọn vì write throughput cực cao (hàng trăm nghìn writes/giây cho mỗi node) và query theo time range hiệu quả nhờ SSTables sorted by timestamp. Query lấy posts trong 24h gần nhất từ ~500 followed users.

Kết quả từ cả hai query được merge và rank (theo chronological + engagement score), chọn ra top 50 posts để trả về. Feed được cache lại vào Redis (TTL 60s) trước khi trả response — để request kế tiếp là cache hit.

Bước 8: Response Journey (đường về)

Response đi ngược: App Server → L7 LB → L4 LB → CDN edge → trình duyệt. Tại L7 LB, response có thể được nén bằng gzip hoặc brotli để giảm kích thước payload.

CDN edge server cache các static assets (CSS, JS bundle, images) đã được reference trong feed response. Khi trình duyệt nhận HTML/JSON, nó lập tức fire thêm hàng chục request cho images và media — tất cả được serve từ CDN edge gần nhất (Singapore), không cần quay về origin server (US).

Trình duyệt render feed sử dụng HTTP/2 multiplexed streams: CSS, JavaScript, và hàng chục ảnh thumbnail được tải song song trên cùng một TCP connection. Từ lúc nhấn Enter đến khi feed hiển thị: ~200-400ms nếu cache hit, ~500-800ms nếu cache miss. Hàng tỷ lần mỗi ngày, 24/7/365.

Sequence Diagram — Toàn bộ vòng đời


Kiến trúc tổng thể — Full Architecture Diagram

Dưới đây là bức tranh toàn cảnh: mọi component hoạt động cùng nhau để serve một request. Hãy nhìn từ trái sang phải — đó là chiều đi của data.

Đọc diagram: Mỗi box là một building block bạn đã học. Mỗi mũi tên là một network call với latency riêng. Khi thiết kế hệ thống, mục tiêu là giảm số lượng mũi tên mà request phải đi qua — và đó chính xác là lý do caching nằm ở giữa, chặn request trước khi chúng đến database.


Bốn scenario snapshots — So sánh kiến trúc

Cùng một bộ building blocks, nhưng mỗi loại hệ thống ưu tiên khác nhau. Đó là bản chất của system design: không có kiến trúc "đúng" duy nhất — chỉ có kiến trúc phù hợp với yêu cầu cụ thể.


Scenario 1: 🐦 High-traffic social feed (Facebook/Twitter)

Building blocks ưu tiên (xếp hạng):

  1. 🥇 Caching — Pre-computed feed cache quyết định sống còn
  2. 🥈 Database Sharding — Write-heavy workload, hàng triệu posts/phút
  3. 🥉 Load Balancing — Fan-out distribution cho feed generation

Quyết định kiến trúc then chốt:

Social feed phải trả lời câu hỏi: "Khi nào build feed?" Có hai trường phái:

  • Fanout-on-write (push model): Khi user A đăng bài, hệ thống ngay lập tức push post vào feed cache của tất cả follower. User mở app → cache hit → instant feed. Nhưng nếu Taylor Swift (90M follower) post? Đó là 90 triệu write operations — fanout hell.

  • Fanout-on-read (pull model): Không pre-compute gì cả. Khi user mở feed, hệ thống query real-time: lấy danh sách following → lấy recent posts → merge & rank. Không có fanout hell, nhưng mỗi request tốn 50-200ms thay vì 2ms từ cache.

Giải pháp thực tế: Hybrid. Celebrity posts (>10K followers) dùng pull model. Regular user posts dùng push model. Đây là trade-off mà mọi social platform lớn đều phải đối mặt.

Trade-off #1: Freshness vs Latency. Cache TTL ngắn = feed mới hơn nhưng cache miss nhiều hơn. TTL dài = nhanh nhưng user thấy bài cũ.


Scenario 2: 📺 Video streaming platform (Netflix/YouTube)

Building blocks ưu tiên (xếp hạng):

  1. 🥇 CDN / Caching — Video delivery chiếm 80% bandwidth toàn cầu
  2. 🥈 DNS (GeoDNS) — Route user đến CDN node gần nhất
  3. 🥉 Database — Metadata store (title, thumbnails, recommendations)

Quyết định kiến trúc then chốt:

Video streaming khác biệt cơ bản: payload size. Một trang feed JSON có thể 50KB, nhưng một video 1080p dài 10 phút = 500MB. Không thể serve trực tiếp từ origin server — cần CDN ở mọi nơi. Netflix đặt Open Connect Appliance (OCA) tại chính ISP của bạn — video Netflix đến từ thiết bị đặt trong datacenter VNPT/Viettel, không phải từ Mỹ.

TCP vs UDP: Video-on-demand (VOD) dùng TCP qua HTTP (HLS/DASH). Tại sao không UDP? Vì VOD có buffer — 30 giây buffered trước khi xem, nên retransmission của TCP không gây stutter. Live streaming ngược lại: latency quan trọng hơn reliability, nên có thể dùng UDP (WebRTC, SRT) chấp nhận mất vài frame thay vì buffer.

Adaptive bitrate streaming (ABR): Video được encode thành nhiều quality levels (360p, 720p, 1080p, 4K). Client tự động chuyển giữa các level dựa trên bandwidth estimation — mạng chậm tự giảm quality, mạng nhanh tự tăng. Đây là lý do Netflix không bao giờ dừng để buffer (trên mạng tốt).

Trade-off #1: CDN cache hit ratio vs storage cost. Cache tất cả video = hit ratio 100% nhưng cần petabytes storage ở mỗi edge. Chỉ cache popular content (top 20% video = 80% views theo Zipf's law) = tiết kiệm nhưng long-tail videos chậm hơn.


Scenario 3: 📝 Real-time collaborative app (Google Docs)

Building blocks ưu tiên (xếp hạng):

  1. 🥇 HTTP/WebSocket — Low-latency bidirectional sync
  2. 🥈 Consistency — Conflict resolution khi nhiều user edit cùng lúc
  3. 🥉 Load Balancing (sticky sessions) — Giữ user trên cùng server để giảm sync overhead

Quyết định kiến trúc then chốt:

Collaborative editing đối mặt vấn đề cốt lõi: hai người edit cùng một chỗ cùng lúc. User A gõ "Hello" tại vị trí 5, đồng thời User B xóa ký tự tại vị trí 3. Thứ tự apply operations khác nhau → kết quả khác nhau. Đây là bài toán distributed consensus trong real-time.

Hai giải pháp chính:

  • Operational Transform (OT): Dùng bởi Google Docs. Server nhận operations từ tất cả clients, transform chúng dựa trên thứ tự nhận được, rồi broadcast kết quả. Server là single source of truth.
  • CRDT (Conflict-free Replicated Data Types): Dùng bởi Figma. Mỗi operation được thiết kế sao cho thứ tự apply không quan trọng — kết quả luôn converge. Không cần central server nhưng data structure phức tạp hơn.

Caching ít quan trọng ở đây vì data thay đổi liên tục — mỗi keystroke là một mutation. Thay vào đó, WebSocket là backbone: kết nối persistent giữa mỗi client và server, latency target < 100ms cho mỗi operation broadcast.

Trade-off #1: Strong consistency (chậm nhưng zero conflict) vs eventual consistency (nhanh nhưng có thể temporary divergence). Google Docs chọn strong consistency qua OT — mỗi edit phải qua central server trước khi broadcast.


Scenario 4: 💬 Chat application (WhatsApp/Slack)

Building blocks ưu tiên (xếp hạng):

  1. 🥇 TCP/WebSocket — Persistent connection cho instant message delivery
  2. 🥈 DNS — Initial connection routing đến đúng server region
  3. 🥉 Database — Message store với ordering guarantee

Quyết định kiến trúc then chốt:

Chat app phải giải quyết vấn đề connection management: WhatsApp có 2 tỷ users. Nếu mỗi user giữ 1 WebSocket connection, đó là 2 tỷ persistent TCP connections. Mỗi server Linux chịu được ~1M connections (với tuning), tức cần tối thiểu 2000 servers chỉ để giữ connections.

Message delivery cũng có hai trường phái:

  • Fan-out-on-write (push): Khi User A gửi tin nhắn trong group 500 người, server push message đến tất cả 500 WebSocket connections ngay lập tức. Đơn giản nhưng group chat lớn tạo spike.
  • Fan-out-on-read (pull): Server chỉ lưu message. Mỗi client tự poll/pull messages khi online. Giảm write amplification nhưng tăng read latency.

WhatsApp chọn push model cho 1-1 chat và small groups. Slack dùng hybrid: push cho real-time + pull khi user scroll lịch sử.

Message ordering là non-negotiable: tin nhắn phải hiển thị đúng thứ tự. Giải pháp: Snowflake ID (timestamp-based unique ID) — mỗi message có ID chứa timestamp, đảm bảo ordering mà không cần global lock. Database sharding theo chat_id để messages cùng conversation nằm trên cùng shard → ordering guaranteed.

Trade-off #1: Delivery guarantee (at-least-once + dedup) vs latency. Mỗi message cần ACK từ recipient — nếu không nhận ACK, retry. Nhưng retry có thể tạo duplicate → cần idempotency key (message ID) để dedup.


Trade-off matrix — So sánh 4 scenarios

Bảng dưới đây tổng hợp cách mỗi hệ thống sử dụng building blocks khác nhau. Hãy đọc theo cột để thấy một hệ thống ưu tiên gì, và đọc theo hàng để thấy cùng một building block được dùng khác nhau ra sao.

Building Block🐦 Social Feed📺 Streaming📝 Real-time Collab💬 Chat
DNSGeoDNS, TTL thấp (60s)GeoDNS → CDN node routingStandard DNSGeoDNS, TTL thấp (60s)
TCP vs UDPTCP (HTTP/2)TCP cho VOD + UDP cho liveTCP (WebSocket)TCP (WebSocket)
HTTP versionHTTP/2 multiplexingHTTP/2 + HLS/DASH segmentsHTTP/2 → upgrade WebSocketHTTP/2 → upgrade WebSocket
LB strategyL7, content-based routingL7 + CDN routingL7, sticky sessionsL4 cho persistent connections
Caching🔴 Critical (feed cache)🔴 Critical (video CDN)⚪ Limited (real-time data)🟡 Session cache only
DB scalingSharding (write-heavy)Read replicas (metadata)Strong consistency neededSharding (by chat_id)
Async processingFan-out workers (Kafka)Transcoding pipelineOp log / event sourcingOffline message queue
Ưu tiên #1Cache hit ratioCDN coverage %Operation latency (< 100ms)Delivery guarantee (0 loss)
Nightmare scenarioCelebrity post → fanout stormViral video → CDN cache missSplit-brain → data divergenceMessage reordering

TIP

💡 Insight quan trọng: Không có building block nào "quan trọng nhất" một cách tuyệt đối. Caching là sống còn cho Social Feed nhưng gần như vô dụng cho Real-time Collab. Đây chính là tư duy system design: hiểu requirements trước, chọn building blocks sau.


Checklist ghi nhớ — Phase 1 Mastery

✅ Checklist triển khai

DNS & Networking

  • [ ] Giải thích được toàn bộ DNS resolution chain: browser cache → OS cache → recursive resolver → root → TLD → authoritative
  • [ ] Phân biệt được khi nào dùng GeoDNS vs standard DNS và lý do chọn TTL value cụ thể
  • [ ] Tính được tổng RTT cost cho TCP + TLS handshake đến một server ở region cụ thể

Transport Layer

  • [ ] Giải thích được tại sao TCP cho web app và streaming VOD, nhưng UDP phù hợp cho live streaming và gaming
  • [ ] Mô tả được TLS 1.3 handshake flow và lợi ích của 0-RTT resumption
  • [ ] Hiểu tại sao connection reuse (HTTP/2, keep-alive) quan trọng cho performance

HTTP & Application Protocol

  • [ ] So sánh được HTTP/1.1, HTTP/2, HTTP/3 và biết khi nào dùng cái nào
  • [ ] Giải thích HPACK header compression và multiplexing trong HTTP/2
  • [ ] Biết khi nào HTTP request/response không đủ → cần WebSocket (real-time, bidirectional)

Load Balancing

  • [ ] Phân biệt L4 vs L7 load balancing: tốc độ vs thông minh
  • [ ] Chọn đúng LB algorithm cho use case: Round Robin, Least Connections, IP Hash, Consistent Hashing
  • [ ] Thiết kế health check strategy: TCP probe vs HTTP check vs deep health check

Caching

  • [ ] Xác định được caching layer phù hợp: browser → CDN → reverse proxy → application → database
  • [ ] Chọn đúng caching pattern: Cache-Aside, Read-Through, Write-Through, Write-Behind
  • [ ] Xử lý được cache invalidation, thundering herd, và cache stampede

Database

  • [ ] Chọn SQL vs NoSQL dựa trên data model và access pattern thực tế
  • [ ] Thiết kế shard key tránh hot spots và cross-shard queries
  • [ ] Cấu hình replication topology: master-slave cho read-heavy, multi-master cho write-heavy

System Thinking

  • [ ] Vẽ được full architecture diagram cho một hệ thống với tất cả building blocks
  • [ ] Nhận diện bottleneck và single point of failure trong kiến trúc
  • [ ] Đánh giá trade-offs giữa consistency, availability, latency, và throughput cho scenario cụ thể

Bài tập luyện tập

Bài 1: Request Lifecycle Analysis — Foundation

🧠 Quiz

Câu 1: Một user ở Hà Nội truy cập https://shopee.vn/flash-sale. Request đi qua các bước: DNS → TCP → TLS → HTTP → LB → App → Cache → DB. Nếu Redis cache hit, bước nào bị bỏ qua hoàn toàn?

  • [ ] A. DNS Resolution — vì cache hit nên không cần resolve domain
  • [ ] B. TLS Handshake — vì data đã cached nên không cần mã hóa
  • [x] C. Database Query — vì data đã có trong Redis cache
  • [ ] D. L7 Load Balancing — vì cache hit xảy ra trước khi đến LB

Giải thích: Cache hit xảy ra ở Application Server level (bước 6), sau khi request đã đi qua DNS, TCP, TLS, HTTP, L4 LB, và L7 LB. Chỉ có Database Query (bước 7) bị skip. DNS vẫn cần để resolve domain, TLS vẫn cần để mã hóa connection, LB vẫn cần để route request đến đúng app server. Cache không bypass network layers — nó bypass storage layers.

🧠 Quiz

Câu 2: Bạn đang thiết kế hệ thống e-commerce và phải chọn giữa fanout-on-writefanout-on-read cho tính năng "Sản phẩm yêu thích đang giảm giá". Hệ thống có 10M users, mỗi user follow trung bình 50 shops, flash sale xảy ra 3 lần/ngày. Phương án nào phù hợp hơn?

  • [ ] A. Fanout-on-write — vì cần notify tất cả users ngay lập tức khi flash sale bắt đầu
  • [x] B. Fanout-on-read — vì 10M × 50 shops × 3 sales = quá nhiều writes, và không phải tất cả users đều online
  • [ ] C. Không cần fanout — dùng polling mỗi 5 giây từ client
  • [ ] D. Fanout-on-write cho VIP users, fanout-on-read cho còn lại

Giải thích: Fanout-on-write sẽ tạo 1.5 tỷ write operations/ngày (10M × 50 × 3) — phần lớn lãng phí vì nhiều user không online lúc flash sale. Fanout-on-read chỉ query khi user thực sự mở app. Đáp án D (hybrid) nghe hay nhưng không cần thiết ở đây vì flash sale là event-driven, không phải continuous feed. Polling (C) tạo quá nhiều unnecessary requests.

🧠 Quiz

Câu 3: Netflix cần serve cùng một video cho 100,000 users ở Việt Nam cùng lúc. Kết hợp building blocks nào hiệu quả nhất?

  • [ ] A. L7 LB + Application Server + Database — serve video trực tiếp từ origin
  • [ ] B. GeoDNS + L4 LB + Application Server — route đến server gần nhất
  • [x] C. GeoDNS + CDN edge (ISP-level) + Adaptive Bitrate — serve từ cache gần nhất
  • [ ] D. DNS Round Robin + Redis Cache + Cassandra — cache video trong memory

Giải thích: Video 500MB × 100K users = 50 TB bandwidth. Không thể serve từ origin server (A) hay qua LB (B) — network sẽ saturate. Redis cache (D) cho video là vô nghĩa — video quá lớn cho in-memory cache. Chỉ có CDN edge + ABR (C) là viable: video được cache tại ISP-level CDN (Open Connect Appliance), GeoDNS route user đến CDN node gần nhất, và ABR tự động adjust quality theo bandwidth.

🧠 Quiz

Câu 4: Hai engineer tranh luận về kiến trúc chat app. Engineer A muốn dùng HTTP long-polling (client giữ request mở, server respond khi có message mới). Engineer B muốn dùng WebSocket (persistent bidirectional connection). Với 1M concurrent users, ai đúng và tại sao?

  • [ ] A. Engineer A — HTTP long-polling đơn giản hơn và tương thích với mọi firewall/proxy
  • [ ] B. Engineer A — vì HTTP/2 server push có thể thay thế WebSocket
  • [x] C. Engineer B — WebSocket tiết kiệm overhead hơn cho high-frequency bidirectional messaging
  • [ ] D. Cả hai sai — nên dùng UDP cho chat vì nhẹ hơn TCP

Giải thích: Long-polling yêu cầu mỗi message = 1 HTTP request/response cycle (headers, TLS overhead). Với 1M users gửi/nhận ~50 messages/phút, đó là 50M HTTP requests/phút — header overhead khổng lồ. WebSocket chỉ cần 1 handshake rồi gửi data frames nhẹ (~6 bytes overhead vs ~800 bytes HTTP headers). HTTP/2 server push (B) không thiết kế cho arbitrary server-initiated messages. UDP (D) không đảm bảo delivery — tin nhắn bị mất là không chấp nhận được.


Bài 2: 🏗️ Architecture Drag-and-Drop — Thiết kế kiến trúc đặt xe (Uber/Grab)

Đề bài: Thiết kế kiến trúc cho hệ thống ride-hailing với yêu cầu:

  • 10M riders, 2M drivers active cùng lúc
  • Driver gửi GPS location mỗi 4 giây
  • Rider cần thấy drivers gần nhất trong < 500ms
  • Matching rider → driver trong < 3 giây
  • Trip history stored vĩnh viễn

Building blocks có sẵn (hãy "ghép" vào vị trí phù hợp):

BlockChức năng
📡 GeoDNSRoute user đến region server gần nhất
🔀 L4 LBTCP connection routing
🔀 L7 LB (sticky)WebSocket session persistence
🖥️ Location ServiceNhận + xử lý driver GPS updates
🖥️ Matching ServiceTìm driver gần nhất cho rider
🖥️ Trip ServiceQuản lý trip lifecycle
💾 Redis (GeoHash)In-memory geospatial index cho driver locations
📊 CassandraTime-series GPS data + trip history
🐘 PostgreSQLUser profiles, payment, driver info
📬 KafkaAsync event processing (notifications, analytics)
⚡ CDNStatic assets (app bundle, map tiles)
📱 WebSocketReal-time bidirectional communication

Hãy thiết kế:

  1. Driver location update flow (GPS → storage)
  2. Rider request flow (open app → see nearby drivers)
  3. Matching flow (rider requests ride → matched with driver)
💡 Gợi ý
  • Driver gửi GPS mỗi 4 giây = 2M × 0.25 = 500K writes/giây. Database nào chịu nổi?
  • Rider cần query "drivers trong bán kính 2km" — data structure nào hỗ trợ geospatial query nhanh?
  • Matching cần đọc driver locations + driver status + rider preferences trong < 3 giây — cần cache hay DB?
  • WebSocket cho real-time updates (driver location moving on map, trip status changes)
✅ Lời giải — Architecture Diagram

Flow phân tích:

① Driver Location Update (500K writes/giây):

  • Driver App → WebSocket → Location Service
  • Location Service ghi Redis (GeoHash) — in-memory, chịu 500K writes/s dễ dàng
  • Async ghi Cassandra qua Kafka (GPS history cho analytics, không cần real-time)
  • Redis GeoHash cho phép query GEORADIUS trong O(N+log(M)) — cực nhanh

② Rider Xem Nearby Drivers (< 500ms):

  • Rider App → WebSocket → Location Service
  • Location Service query Redis GEORADIUS (bán kính 2km) → trả về list driver IDs + locations
  • Filter theo driver status (available only) → trả về rider qua WebSocket
  • Server push location updates mỗi 4 giây qua cùng WebSocket connection

③ Matching Flow (< 3 giây):

  • Rider request ride → Matching Service
  • Matching Service query Redis (nearby available drivers) + PostgreSQL (driver rating, vehicle type)
  • Rank drivers → chọn best match → notify driver qua WebSocket
  • Driver accept → Trip Service tạo trip record trong PostgreSQL + gửi event qua Kafka
  • Kafka triggers: notification to rider, billing setup, analytics event

Trade-offs:

  • Redis single point of failure: Dùng Redis Cluster (6+ nodes) với replication. Nếu Redis down, fall back to Cassandra (chậm hơn nhưng vẫn hoạt động)
  • WebSocket sticky sessions: L7 LB phải route cùng user đến cùng WebSocket Gateway instance → dùng consistent hashing trên user_id
  • Write amplification: 500K GPS writes/s × 2 (Redis + Cassandra) = 1M writes/s. Giải pháp: batch Cassandra writes mỗi 30 giây thay vì real-time

Liên kết học tiếp

Từ khóa glossary: request lifecycle, building blocks, architecture diagram, fanout-on-write, fanout-on-read, CDN, GeoDNS, WebSocket, cache hit ratio, sharding, consistent hashing, adaptive bitrate

Tìm kiếm liên quan: system design interview capstone, full request trace, end-to-end architecture, building blocks comparison