系統架構#
推薦系統不只是演算法,更是一個完整的工程系統。本章介紹推薦系統的架構設計。
三層架構#
Netflix 架構#
Netflix 的推薦系統架構是業界標杆,分為三層:
flowchart TB
subgraph 在線層["🟢 在線層 Online"]
direction LR
O1[實時響應請求]
O2[使用實時資料]
O3[毫秒級延遲]
end
subgraph 近線層["🟡 近線層 Nearline"]
direction LR
N1[使用實時資料]
N2[非同步處理]
N3[特徵更新]
end
subgraph 離線層["🔵 離線層 Offline"]
direction LR
F1[批量處理]
F2[全量資料]
F3[模型訓練]
end
離線層 --> 近線層 --> 在線層
style 在線層 fill:#e8f5e9
style 近線層 fill:#fff3e0
style 離線層 fill:#e3f2fd各層特點#
| 階層 | 資料 | 服務 | 典型任務 |
|---|---|---|---|
| 在線 | 實時 | 實時 | 排序、過濾、業務規則 |
| 近線 | 實時 | 非同步 | 特徵更新、模型增量更新 |
| 離線 | 全量 | 批量 | 模型訓練、全量計算 |
在線層設計#
核心要求#
在線層必須保證:
- 低延遲(< 100ms)
- 高可用(99.99%)
- 可降級
服務流程#
flowchart LR
A[用戶請求] --> B[召回服務]
B --> C[排序服務]
C --> D[重排服務]
D --> E[返回結果]
B -.-> B1[多路召回]
C -.-> C1[CTR 預估]
D -.-> D1[業務規則]
style A fill:#e3f2fd
style E fill:#e8f5e9降級策略#
當上游服務異常時,需要有 Plan B:
| 異常情況 | 降級策略 |
|---|---|
| 個性化召回失敗 | 返回熱門排行榜 |
| 排序模型超時 | 使用簡單規則排序 |
| 特徵服務異常 | 使用預設特徵值 |
API 設計#
推薦 API 示例
GET /recommend
參數:
- user_id: 用戶 ID(必需)
- page_id: 頁面 ID
- position_id: 推薦位 ID
- size: 請求數量
- offset: 偏移量(翻頁)
返回:
{
"recommend_id": "xxx", // 曝光 ID,用於追蹤
"items": [
{
"id": "item_123",
"title": "...",
"score": 0.95
}
],
"size": 10
}離線層設計#
典型任務#
資料清洗 → 特徵工程 → 模型訓練 → 離線評估 → 推送上線資料管理#
| 組件 | 作用 | 工具 |
|---|---|---|
| 資料湖 | 存儲原始日誌 | HDFS、S3 |
| 資料倉庫 | 結構化存儲 | Hive、Spark SQL |
| 特徵平台 | 特徵計算和存儲 | 自研或開源 |
模型訓練#
# 典型的離線訓練流程
def train_model():
# 1. 讀取訓練資料
df = spark.read.parquet("hdfs://data/training")
# 2. 特徵工程
features = feature_engineering(df)
# 3. 模型訓練
model = train(features)
# 4. 離線評估
metrics = evaluate(model, test_data)
# 5. 模型推送
if metrics['auc'] > threshold:
push_to_online(model)近線層設計#
流計算架構#
用戶行為 → Kafka → Flink/Storm → 特徵更新 → Redis/Cassandra
→ 模型更新 →
→ 推薦結果更新 →Storm 程式設計模型#
| 概念 | 說明 | 類比 |
|---|---|---|
| Spout | 資料源 | 水龍頭 |
| Bolt | 資料處理器 | 水管連接處 |
| Tuple | 資料單元 | 水 |
| Topology | 資料流圖 | 水管系統 |
實時更新示例#
以 Item-CF 為例,用戶產生新行為時:
- 取出用戶歷史行為物品列表
- 新物品與歷史物品構成「物品對」
- 更新這些物品對的共現次數
- 重新計算相似度
資訊流架構#
Feed 系統特點#
| 特點 | 說明 |
|---|---|
| 海量內容 | 每天新增百萬級內容 |
| 實時性要求高 | 新聞時效性 |
| 多路召回 | 興趣標籤、協同過濾、熱門等 |
| 混合排序 | 多目標優化(時長、點擊、多樣性) |
典型架構#
flowchart LR
subgraph 內容處理
A1[內容入庫] --> A2[內容分析] --> A3[建立索引]
end
subgraph 多路召回
B1[標籤召回]
B2[CF 召回]
B3[熱門召回]
end
subgraph 排序展示
C1[融合] --> C2[排序] --> C3[重排] --> C4[展示]
end
A3 --> B1
A3 --> B2
A3 --> B3
U[用戶請求] --> B1
U --> B2
U --> B3
B1 --> C1
B2 --> C1
B3 --> C1
style U fill:#e3f2fd
style C4 fill:#e8f5e9搜尋、推薦、廣告的關係#
對比#
| 維度 | 搜尋 | 推薦 | 廣告 |
|---|---|---|---|
| 用戶意圖 | 明確 | 模糊 | 被動接收 |
| 目標 | 相關性 | 滿足興趣 | 商業變現 |
| 資訊取得 | 主動 | 被動 | 被動 |
| 個性化程度 | 較低 | 高 | 高 |
統一架構的可能性#
三者都可以抽象為:過濾候選 → 排序候選 → 個性化輸出
┌─────────────────────────────────────┐
│ 統一架構 │
│ │
Query/User ─────→│ 召回層 ──→ 排序層 ──→ 重排層 │──→ 結果
│ │
└─────────────────────────────────────┘一些公司已經在嘗試統一搜尋和推薦的架構,共享底層技術堆疊。
存儲選型#
不同資料的存儲方案#
| 資料類型 | 特點 | 推薦存儲 |
|---|---|---|
| 用戶/物品特徵 | 批量讀寫 | Cassandra、HBase |
| 模型參數 | 鍵值對 | Redis |
| 推薦結果 | 列表形式 | Redis sorted set |
| 隱向量 | 稠密向量 | 檔案 + MMAP |
| 倒排索引 | 高效檢索 | ElasticSearch |
列式資料庫#
Cassandra vs HBase:
- Cassandra:去中心化,可調一致性,讀寫性能更好
- HBase:強一致性,與 Hadoop 生態集成好
模型存儲#
| 方式 | 適用場景 |
|---|---|
| PMML | 小規模模型,跨語言部署 |
| Pickle/Joblib | Python 生態內部使用 |
| SavedModel | TensorFlow 模型 |
| ONNX | 跨框架通用格式 |
實踐建議#
從簡單開始#
不要一開始就追求完美架構:
- 中小公司:先用單機,充分發揮單機性能
- 先跑通流程,再優化性能
- 根據實際瓶頸逐步升級
架構演進路線#
timeline
title 推薦系統架構演進
階段 1 單機版本
: 協同過濾 + 熱門
: MySQL/Redis
: 定時批量更新
階段 2 分離離線在線
: 離線:Spark 計算
: 在線:微服務架構
階段 3 加入近線層
: Kafka + Flink
: 實時特徵更新
階段 4 完整架構
: 多路召回
: 深度學習排序
: 完善監控體系總結#
| 要點 | 說明 |
|---|---|
| 三層架構 | 在線/近線/離線,各有分工 |
| 在線層 | 低延遲、高可用、可降級 |
| 離線層 | 批量計算、模型訓練 |
| 近線層 | 流計算、實時更新 |
| 存儲選型 | 根據資料特點選擇合適的存儲 |
| 演進路線 | 從簡單開始,按需升級 |