經典架構拆解 · 02 — Uber 即時派單架構
CLOUD
上一篇看完 Netflix 的全球串流架構,這次我們切到另一端:即時地理配對。Netflix 的痛點是「把大檔案推到使用者附近」,Uber 的痛點是「在一秒內,把某個 GPS 座標的乘客,和半徑 500 公尺內最適合的司機配對起來」。
這是兩種規模差很多的問題,但 Uber 的解法對 PCA 考生特別有用,因為它把**地理分片(geo sharding)和事件驅動工作流(event-driven workflow)**這組經典組合示範得很清楚。
為什麼值得拆解
Uber 的派單系統不只是「一個大型的 matching engine」。它同時要處理:
- 即時位置流:全球所有司機每 4 秒上報 GPS 位置。
- 地理查詢:以乘客為中心,在地圖上找出符合車種、評分、路況的候選司機。
- 配對工作流:司機接受、拒絕、取消、到場、上車、下車,每一步都可能失敗,需要可重試的狀態機。
這三件事剛好對到 PCA 考試裡最容易被忽略的三個能力:水平分片策略、低延遲 NoSQL 選型、長流程(long-running workflow)建模。
商業規模與壓力
根據 Uber 2024 年 Q4 財報公開揭露,Uber 平台在 2024 年全年完成約 113 億次行程(Trips),月活躍平台使用者約 1.71 億。根據 Uber Engineering Blog 於 2022 年公開的文章,派單系統需要處理每秒數百萬次的地理查詢,並在尖峰時段(例如跨年夜、機場外大型活動結束)承受 10 倍以上流量。
這代表幾件事:
- 單一資料庫表撐不住:一張「司機位置」表如果沒分片,查詢幾分鐘就會把整個系統拖垮。
- 地理查詢不能用 SQL
WHERE distance < X:就算有空間索引,跨 region 查詢的延遲也沒辦法接受。 - 每一趟行程都是一個長流程:可能跨 30 分鐘、橫跨好幾個城市,中間還會碰到網路斷線跟伺服器重啟。
架構演進簡史
| 年份 | 里程碑 | 意義 |
|---|---|---|
| 2014–2015 | 舊版 Dispatch(DISCO)用 MongoDB 空間索引 | 城市數量增加後,單一 DB 成為瓶頸 |
| 2015 | 自研 Ringpop 一致性雜湊(consistent hashing) | 讓同一城市的請求永遠落到同一組節點,避免跨節點查詢 |
| 2018 | H3 地理索引開源 | 把地球切成六角形格子(hexagon),取代經緯度矩形分片 |
| 2016–2017 | Cadence workflow 開源 | 把派單、費用結算等長流程從「ad-hoc state machine」改為宣告式 workflow |
| 2019 | Temporal 從 Cadence 分支(後繼專案) | 原 Cadence 作者另起爐灶,成為日後的主流 workflow engine |
| 2021+ | 全站事件匯流改用 Apache Kafka 為主幹 | 解耦下單、配對、計費、通知等子系統 |
核心技術決策
| 決策 | 為何這樣選 | 替代方案與為何沒選 |
|---|---|---|
| 用 H3 六角形格子做地理分片 | 六角形的相鄰距離一致,比經緯度矩形更公平;可分多層級,從城市到街角都能表達 | 純經緯度矩形:邊界扭曲(極區特別嚴重)、相鄰距離不均 |
| Ringpop 一致性雜湊定位服務節點 | 當節點增減時,只有 1/N 的請求需要重新路由,不用全體重分配 | 傳統 sharding key:節點擴容時大量熱點漂移,連線風暴 |
| Cadence/Temporal 管理派單流程 | 派單是跨小時、跨服務、跨失敗的長流程,用一般訊息佇列無法描述「下一步等多久才 timeout」 | 自建 state machine:每種失敗路徑都要自己寫重試與 timeout 邏輯 |
| 位置資料用 in-memory NoSQL + 分層持久化 | 司機位置寫入頻率極高、讀取延遲要求 < 50ms,用 SSD 資料庫撐不住 | 直接寫 PostgreSQL:寫入熱點會馬上打爆 |
| 事件匯流用 Kafka | 下單、配對、計費需要強順序保證;消費者可以獨立擴容 | RabbitMQ 或純 REST:無法保證城市內事件順序或回放能力 |
如果用 GCP 重新蓋
在 GCP 上模擬這套架構:
- 即時地理索引: Bigtable 作為 geo index 主力,使用 H3 cell ID 當作 row key,利用其 lexicographic 排序特性做範圍查詢;熱資料另用 Memorystore(Redis)加速。
- 配對與 dispatcher 服務: GKE(regional)部署 dispatcher,搭配 Cloud Service Mesh(前身為 Anthos Service Mesh)做區域親和性路由,對應 Ringpop 的角色。
- 長流程工作流: Cloud Workflows 適合輕量編排;真的要處理 Cadence 等級的持久狀態機,可自架 Temporal on GKE,因為 Temporal 就是 Cadence 的後繼專案。
- 事件匯流: Pub/Sub(或 Kafka on GKE / Confluent Cloud)。需要嚴格順序與長期保留時用 Kafka;純解耦用 Pub/Sub。
- 跨 region 交易資料: Spanner 存行程、帳單、付款紀錄,利用它的 multi-region 強一致能力。
- 離線分析: BigQuery 處理歷史行程與供需熱力圖。
PCA 考點映射
| 考點 | Uber 對應 |
|---|---|
| 地理分區與資料分片 | H3 + Ringpop,題目常問「如何讓查詢不跨 region」 |
| 事件驅動解耦 | Kafka 主幹線讓計費、通知、ETA 推算獨立演進 |
| 長流程工作流(workflow orchestration) | Cadence/Temporal,對應 GCP 的 Cloud Workflows 或自架 Temporal |
常見誤解
- 「Uber 的派單就是 PostGIS + 空間索引」 —— 一般應用這樣做沒問題,但到 Uber 這種規模就不行了。重點不在選哪個 DB,而是先把「查詢範圍」框在同一個 shard 內,資料庫選型反而是次要的。
- 「Cadence 就是 cron job」 —— Cadence/Temporal 是持久化的 workflow engine,可以讓一個函式跑好幾天、就算中途重啟也接著跑。這跟 cron 的 fire-and-forget 差很多。
- 「一致性雜湊只是負載均衡技巧」 —— 在 Uber 的架構裡,它同時也是資料親和性(data locality)機制:把同城市的請求導到同一組節點,快取命中率就跟著衝上去。
來源與延伸閱讀
- Uber Engineering Blog — 派單、H3、Ringpop、Cadence 的原始公開文章。
- H3 官方文件 — 六角形地理索引的開源專案與論文。
- Ringpop 專案頁 — 一致性雜湊實作與設計原則。
- Cadence / Temporal 官方文件 — workflow engine 的設計哲學與 API。
- Uber Q4 2024 Earnings Release — 年度行程數與活躍使用者引用來源。
下一篇:從「即時地理系統」切換到另一個經典問題 —— Stripe 的 API 冪等性設計,看他們如何讓「重複付款」在架構層面就不可能發生。
🎯 換你練習
engineering-architecture-breakdown — 2/6 完成
查看系列全覽 →