「如何設計一個短網址系統(TinyURL / Bitly)?」是全矽谷與全球頂級科技公司在系統設計面試中最高頻出現的經典題目。
這個題目看似簡單(將一個長長個 URL https://example.com/very/long/path?id=123 縮短為 https://tiny.url/aB3x9Z),但背後卻涵蓋了:
- 容量估算與數學建模;
- 字串編碼(Base62)與哈希碰撞(Hash Collisions)解法;
- HTTP 重新導向狀態碼(301 vs. 302)的業務權衡;
- 高併發讀取快取與防穿透防禦。
本文將依照系統設計面試的黃金標準流程,為你提供一份滿分級別的架構設計方案。
1. 需求分析與容量估算(Math Modeling)
1.1 功能與非功能性需求
- 核心功能:
- 輸入原始長網址,生成一個全域唯一的 7 位元短網址。
- 點擊短網址,毫秒級重新導向至原始長網址。
- 支援自定義短網址別名(Custom Alias)與到期時間(TTL)。
- 非功能性需求:
- 極致高可用(99.99%) 與 極低延遲(
< 10ms)。 - 短網址不能被輕易猜測遍歷(安全防爬蟲)。
- 極致高可用(99.99%) 與 極低延遲(
1.2 容量估算
- 寫入 QPS:假設每月新增 1 億(100M)個短網址:
寫入 QPS = 100,000,000 / (30 * 24 * 3600) ≈ 40 QPS - 讀取 QPS(讀寫比 100:1):
讀取 QPS = 40 * 100 = 4,000 QPS (峰值 10,000+ QPS) - 10 年總資料量與字元長度計算:
- 10 年累積短網址數:
100M * 12 * 10 = 120 億 (12 Billion)。 - 短網址字元集採用
[0-9], [a-z], [A-Z]共 62 個字元(Base62)。 - 設短網址長度為
L:62^6 ≈ 568 億(6 位數已足夠,但 7 位數可提供62^7 ≈ 3.5 兆種不重複組合,極大增強安全性與抗碰撞能力)。- 結論:短網址固定採用 7 位元字串(例如
aB3x9Z1)。
- 10 年累積短網址數:
2. 核心編碼演算法:哈希截斷 vs. 分散式 ID + Base62
生成 7 位元短網址主要有兩大設計流派:
2.1 為什麼「分散式 ID + Base62」全面優於「哈希截斷」?
- 雜湊截斷法:因為取了前 7 個字元,必然會發生雜湊碰撞(Hash Collision)。當資料庫達到數十億筆時,碰撞率急劇上升,每次碰撞都必須查詢一次資料庫並加 Salt 重算,寫入延遲不可控。
- 分散式 ID + Base62:發號器保證生成的 64-bit 整數在全域內絕對單調唯一,10 進位轉 62 進位是一個可逆且嚴格一一對應的數學轉換,根本不需要進行任何碰撞檢測,時間複雜度恆定為 O(1)!
3. HTTP 重新導向狀態碼深度抉擇:301 vs. 302 / 307
當使用者訪問 https://tiny.url/7bK9zX 時,伺服器應返回哪種 HTTP 狀態碼?
| 狀態碼 | 瀏覽器行為 | 業務優缺點 |
|---|---|---|
| 301 Moved | 瀏覽器會【永久快取】該重新導向關係 | 伺服器負載極低 (後續訪問不打服務器) |
| Permanently | 下次直接本地跳轉,不再請求短網址服務 | 缺點:無法精確統計點擊次數與用戶分析 |
| 302 Found / | 瀏覽器【不快取】重新導向關係 | 每次點擊均會訪問短網址伺服器, |
| 307 Temporary | 每次點擊都會發起一次請求 | 業務可精確記錄點擊量、來源 IP、地理 |
| Redirect (推薦) | 位置與使用者畫像! |
4. 全鏈路架構設計與多級快取防禦
4.1 資料庫選型(NoSQL vs. SQL)
短網址資料模型非常單純(只需儲存 short_key -> long_url, user_id, created_at, expire_at),且不需要複雜的跨表 JOIN。
- 首選 分散式 NoSQL KV 資料庫(如 AWS DynamoDB 或 MongoDB),以
short_key作為 Partition Key,天然具備水平擴展與自動分片能力。
5. 系統設計面試檢查清單
- 容量估算清晰:明確推導 10 年 120 億短網址需要 7 位元 Base62 字元。
- 核心演算法嚴謹:選擇「分散式 ID 發號器 + Base62」徹底消滅雜湊碰撞。
- 狀態碼權衡到位:清楚闡述 301 與 302 在點擊統計上的架構差異。
- 全鏈路高併發防禦:Redis 快取 + 布隆過濾器徹底防禦快取穿透。
