Bài toán kỹ thuật
Hãy tưởng tượng bạn là kỹ sư tại Uber hoặc Grab. Hệ thống của bạn phải:
- Nhận tọa độ GPS từ hàng triệu tài xế mỗi 4 giây.
- Lưu và lập chỉ mục toàn bộ vị trí này trong bộ nhớ RAM (in-memory) để truy vấn trong dưới 10ms.
- Khi khách gọi xe, tìm và xếp hạng tài xế phù hợp nhất trong bán kính vài km, tính thời gian đến (ETA) dựa trên giao thông thực tế, rồi gửi cuốc xe xuống điện thoại tài xế tức thì — tất cả trong vòng 2 giây.
- Đồng thời, liên tục tính toán giá động (surge pricing) dựa trên tỷ lệ cung-cầu tại từng khu vực, cập nhật mỗi vài giây.
Đây không phải một bài toán CRUD thông thường. Đây là một trong những hệ thống phân tán phức tạp nhất thế giới.
Kiến trúc tổng thể
┌──────────────────────────────────────────────────────────────────┐
│ MOBILE APPS │
│ Rider App ◄──── WebSocket/gRPC ────► Driver App │
│ (Đặt xe, xem bản đồ) (Nhận cuốc, báo vị trí) │
└───────────────────────┬──────────────────────┬───────────────────┘
│ │
REST/gRPC MQTT/gRPC Stream
│ │ (GPS mỗi 4 giây)
┌───────────────────────▼──────────────────────▼───────────────────┐
│ API GATEWAY + Load Balancer │
└───────────────────────┬──────────────────────┬───────────────────┘
│ │
┌──────────────▼────┐ ┌────────────▼──────────────┐
│ Demand Service │ │ Supply/Location Service │
│ (Ride Requests) │ │ (GPS Ingestion) │
└────────┬──────────┘ └────────────┬──────────────┘
│ │
└──────────┬──────────────────┘
▼
┌──────────────────────────────┐
│ Apache Kafka │
│ (Event Streaming Backbone) │
└──────┬───────┬───────┬───────┘
│ │ │
┌─────────▼──┐ ┌─▼──────────┐ ┌──▼──────────────┐
│ Redis GEO │ │ DISCO │ │ Pricing Engine │
│ + H3 Index │ │ Matching │ │ (Surge Pricing) │
│ (Vị trí) │ │ Engine │ │ │
└─────────────┘ └────────────┘ └─────────────────┘
│
▼
┌──────────────────────────────┐
│ RAMEN Push Service │
│ (gRPC/QUIC → Mobile App) │
└──────────────────────────────┘
Sáu trụ cột kiến trúc
1. Location Ingestion — Thu thập GPS tối ưu
App tài xế gửi tọa độ mỗi 4 giây qua các giao thức siêu nhẹ (MQTT, gRPC Streams). Kỹ thuật batching gom nhiều điểm GPS vào một gói tin duy nhất để tiết kiệm pin và băng thông. Tín hiệu GPS nhiễu được lọc bằng Kalman Filter trước khi xử lý.
2. Geospatial Indexing — Chia lưới bản đồ
Thay vì quét toàn bộ database, Uber chia bản đồ thành hàng triệu ô lục giác (H3) hoặc ô vuông (S2 Geometry). Khi khách gọi xe, hệ thống chỉ cần tìm tài xế trong ô lục giác đó và các ô lân cận — giảm không gian tìm kiếm từ hàng triệu xuống vài chục.
3. Event Streaming — Xương sống Kafka
Mọi sự kiện (GPS mới, khách đặt xe, tài xế nhận cuốc) đều đi qua Apache Kafka. Từ Kafka, dữ liệu rẽ nhánh tới nhiều consumer: Redis GEO, Matching Engine, Pricing Engine, Analytics Pipeline. Apache Flink xử lý stream processing theo thời gian thực.
4. DISCO Matching Engine — Ghép cuốc xe
Hệ thống DISCO (Dispatch Optimization) của Uber không đơn giản chỉ tìm tài xế gần nhất. Nó dùng Batched Matching — gom nhiều request trong vài giây rồi giải bài toán phân công tối ưu toàn cục (Global Assignment Problem) để tối thiểu hóa tổng ETA cho tất cả các cặp khách-tài xế.
5. Surge Pricing — Tính giá linh hoạt
Hệ thống liên tục tính toán tỷ lệ cung (số tài xế rảnh) / cầu (số khách đang gọi) tại mỗi ô lục giác H3. Khi cầu vượt cung, hệ số nhân giá (surge multiplier) tự động tăng, vừa khuyến khích tài xế đổ về khu vực đó, vừa lọc bớt nhu cầu không thiết yếu.
6. RAMEN — Giao tiếp Real-time
RAMEN (Real-time Asynchronous Messaging Network) là hạ tầng đẩy thông báo của Uber. Ban đầu dùng SSE (Server-Sent Events), sau chuyển sang gRPC over QUIC/HTTP3 để truyền song công (full-duplex). Duy trì hàng triệu kết nối sống đồng thời, đảm bảo cuốc xe được đẩy tới tài xế trong mili-giây.
So sánh công nghệ giữa các hãng
| Thành phần | Uber | Grab | Lyft |
|---|---|---|---|
| Geospatial Index | H3 (tự phát triển) | Geohash + S2 | S2 Geometry |
| Event Bus | Kafka | Kafka | Kafka + Flink |
| Matching | DISCO (Node.js + Ringpop) | Fulfilment Platform (Go) | Marketplace (Python + C++) |
| Push System | RAMEN (gRPC/QUIC) | WebSocket + FCM | gRPC Streams |
| AI/ML | ETA DeepETA, Batched Matching | DispatchGym (RL) | Map Matching + ML Residual |
| Service Mesh | Custom | Consul → Istio | Envoy |
| Framework | Go, Java, Node.js | Grab-Kit (Go) | Python, Go |
Các bài engineering blog gốc
Toàn bộ series này được tổng hợp từ các nguồn kỹ thuật chính thức:
- Uber Engineering: “H3: Uber’s Hexagonal Hierarchical Spatial Index”, “DISCO: The Brain Behind Every Driver Match”, “RAMEN: Real-time Asynchronous Messaging”, “DeepETA”
- Grab Engineering: “Grab’s Fulfilment Platform Architecture”, “DispatchGym”, “From Consul to Istio”
- Lyft Engineering: “Real-time Map Matching”, “ETA Prediction”
Bắt đầu hành trình với Phần 1 — Location Ingestion: Thu thập hàng triệu tọa độ GPS mỗi giây. Chúng ta sẽ tìm hiểu vì sao HTTP REST không đủ tốt và các giao thức thay thế mà Uber/Grab dùng.