蝦皮快速搜尋與商品推薦的技術實現:從資料收集到個性化推薦
蝦皮(Shopee)作為東南亞領先的電商平台,每天處理數億次搜尋與推薦請求,能在毫秒內回應用戶輸入(如「無線耳機 1000-2000 元」)並提供個性化商品推薦(如「你可能也喜歡」)。這背後是資料索引、快取、分散式搜尋引擎與推薦演算法的協作。本文深入解析蝦皮的快速搜尋與商品推薦機制,聚焦於如何收集用戶行為資料並實現快速推薦,結合 2025 年的技術趨勢(如 Elasticsearch、Redis 與協同過濾),並提供 PHP/Laravel 程式碼範例,方便你應用於電商專案。內容參考蝦皮等電商平台的公開案例與業界最佳實踐。
1. 核心挑戰與技術架構
挑戰分析
- 資料規模:蝦皮擁有數億商品,每筆包含名稱、價格、類別、屬性(如顏色、尺寸)與庫存狀態,傳統 SQL 查詢效率低下(O(n) 時間複雜度)。
- 查詢複雜性:支援多語言關鍵字搜尋(繁中、英文、泰文等)、範圍篩選(價格、評價)、排序(銷量、相關性)與即時庫存檢查。
- 高併發:雙 11 等促銷活動每秒數十萬請求,需毫秒級響應。
- 即時推薦:根據用戶瀏覽、搜尋、購買與收藏行為,動態生成個性化商品推薦。
- 用戶資料收集:需即時追蹤行為(如點擊、加入購物車),並整合歷史數據進行分析。
解決策略
- 搜尋引擎:Elasticsearch (ES) 提供倒排索引與多維查詢,實現快速搜尋。
- 快取層:Redis 快取熱門搜尋與推薦結果,降低伺服器負載。
- 推薦系統:協同過濾(Collaborative Filtering)與基於內容的推薦,結合用戶行為數據。
- 資料收集:Kafka 異步收集用戶行為,儲存至 MongoDB 或 MySQL。
- 技術棧:後端 PHP/Laravel,前端 Vue.js/React,搜尋 Elasticsearch,快取 Redis,資料庫 MySQL/PostgreSQL,消息隊列 Kafka。
2. 快速搜尋的實現:Elasticsearch 核心
Elasticsearch 是蝦皮搜尋的核心,透過倒排索引將關鍵字搜尋從 O(n) 降至 O(log n),並支援多語言與範圍查詢。以下是實現細節:
搜尋流程
- 資料索引:商品資料(名稱、價格、類別、庫存)從 MySQL 同步到 ES,使用 Logstash 或 PHP 腳本。
- 查詢處理:用戶輸入(如「無線耳機」)轉為 ES 查詢,結合 bool query(match、filter)與 multi_match 支援多語言。
- 排序與分頁:按銷量、價格或相關性排序,使用 from/size 實現分頁。
PHP 整合範例
以下展示如何用 Laravel 與 Elasticsearch 實現商品搜尋:
php
// Composer: composer require elasticsearch/elasticsearch
use Elasticsearch\ClientBuilder;
class ProductSearchController extends Controller
{
public function search(Request $request)
{
$client = ClientBuilder::create()->setHosts(['elasticsearch:9200'])->build();
$params = [
'index' => 'products',
'body' => [
'query' => [
'bool' => [
'must' => [
['multi_match' => [
'query' => $request->input('keyword', '無線耳機'),
'fields' => ['name^2', 'description', 'category'] // 名稱權重更高
]]
],
'filter' => [
['range' => ['price' => ['gte' => 1000, 'lte' => 2000]]],
['term' => ['in_stock' => true]]
]
]
],
'sort' => [['sales' => 'desc'], ['_score' => 'desc']],
'from' => ($request->input('page', 1) - 1) * 20,
'size' => 20
]
];
$response = $client->search($params);
return response()->json([
'results' => $response['hits']['hits'],
'total' => $response['hits']['total']['value']
]);
}
}
- 時間複雜度:O(log N),N 為商品數量,基於 B+ 樹索引。
- 空間複雜度:O(N * M),M 為平均屬性數。
- 實務應用:蝦皮使用 ES 處理多語言搜尋(如「headphones」「耳機」),並結合庫存檢查確保結果即時性。
3. 收集用戶資料:行為追蹤與儲存
快速推薦依賴於即時收集與分析用戶行為數據(如瀏覽、點擊、加入購物車、購買)。以下是實現方式:
收集流程
- 前端追蹤:用 JavaScript SDK(如自訂事件追蹤或 Firebase Analytics)記錄行為(點擊商品、搜尋關鍵字、停留時間)。
- 後端接收:Laravel API 接收事件,透過 Kafka 異步儲存,確保高併發處理。
- 資料儲存:MongoDB(非結構化行為數據)或 MySQL(結構化訂單數據)。
- 即時處理:Redis 儲存短期行為數據(如最近 24 小時瀏覽),供推薦系統快速訪問。
PHP 範例:記錄用戶行為
php
use Predis\Client;
use Illuminate\Support\Facades\DB;
class UserBehaviorController extends Controller
{
public function track(Request $request)
{
$redis = new Client();
$userId = $request->input('user_id');
$productId = $request->input('product_id');
$action = $request->input('action'); // view/click/add_to_cart
// 儲存到 Redis(短期行為)
$redis->zIncrBy("user:$userId:actions", 1, "$action:$productId");
$redis->expire("user:$userId:actions", 86400); // 24 小時過期
// 異步儲存到 MySQL
DB::table('user_actions')->insertAsync([
'user_id' => $userId,
'product_id' => $productId,
'action' => $action,
'created_at' => now()
]);
return response()->json(['status' => 'tracked']);
}
}
- 時間複雜度:O(1),Redis zIncrBy 和 MySQL 插入為常數時間。
- 空間複雜度:O(U * A),U 為用戶數,A 為平均行為數。
- 實務應用:蝦皮透過類似機制追蹤用戶點擊與購物車行為,結合 Kafka 處理高峰期事件流。
4. 快速商品推薦:協同過濾與快取
推薦流程
蝦皮的商品推薦(如「你可能也喜歡」)主要基於協同過濾(Collaborative Filtering)與基於內容的推薦:
- 用戶-商品矩陣:用 Redis Sorted Set 儲存用戶行為(如瀏覽、購買),形成交互矩陣。
- 相似度計算:計算用戶間或商品間的相似度(如 Jaccard 相似度),找出相關商品。
- 即時推薦:用 Redis 快取 Top-N 推薦結果,結合 ES 過濾已下架商品。
- 離線計算:Laravel Job 定期計算相似度矩陣,儲存至 Redis,減少即時計算負擔。
PHP 範例:協同過濾推薦
php
use Predis\Client;
class ProductRecommendationController extends Controller
{
public function recommend(Request $request)
{
$redis = new Client();
$userId = $request->input('user_id');
$k = $request->input('limit', 5);
// 獲取用戶行為
$userActions = $redis->zRange("user:$userId:actions", 0, -1);
$similarProducts = [];
// 協同過濾:找其他用戶也瀏覽/購買的商品
foreach ($redis->keys('user:*:actions') as $otherUserKey) {
$otherUserId = str_replace('user:', '', str_replace(':actions', '', $otherUserKey));
if ($otherUserId == $userId) continue;
$intersection = $redis->zInter("user:$userId:actions", [$otherUserKey]);
$similarProducts = array_merge($similarProducts, $intersection);
}
// 計數並排序
$productCounts = array_count_values($similarProducts);
arsort($productCounts);
$recommendedIds = array_slice(array_keys($productCounts), 0, $k);
// 從 ES 獲取商品詳情
$client = ClientBuilder::create()->setHosts(['elasticsearch:9200'])->build();
$params = [
'index' => 'products',
'body' => [
'query' => [
'terms' => ['_id' => $recommendedIds]
]
]
];
$results = $client->search($params)['hits']['hits'];
// 快取推薦結果
$redis->zAdd("recommend:user:$userId", array_combine($recommendedIds, array_values($productCounts)));
$redis->expire("recommend:user:$userId", 3600);
return response()->json(['recommendations' => $results]);
}
}
- 時間複雜度:O(U * P),U 為用戶數,P 為平均行為數(Redis 集合交集)。離線計算可降至 O(1) 查詢。
- 空間複雜度:O(P),儲存交集與推薦結果。
- 實務應用:蝦皮在商品詳情頁顯示「買這個的人也買」,基於用戶行為與類別相似度。
快取優化
- Redis Sorted Set:儲存用戶推薦清單,鍵為 recommend:user:$userId,TTL 1 小時。
- 離線批次:用 Laravel Scheduler 每晚計算相似度矩陣,儲存至 Redis。
5. 資料庫與資料同步
- 主要資料庫:MySQL 儲存商品與訂單資料,複合索引(name、price、category)加速查詢。
- 非結構化資料:MongoDB 儲存用戶行為日誌,支援靈活查詢。
- 同步機制:Kafka 異步將新商品、庫存更新或用戶行為推送到 ES/Redis,確保即時性。
SQL 範例(備援 ES)
sql
CREATE INDEX idx_product_name_price ON products (name, price);
SELECT * FROM products
WHERE price BETWEEN 1000 AND 2000
AND category = 'electronics'
AND in_stock = true
ORDER BY sales DESC
LIMIT 20;
6. 前端與用戶體驗優化
- 即時搜尋建議:Vue.js/React 透過 AJAX 發送部分輸入(如「耳機」),ES 提供 fuzzy matching 建議(如「無線耳機」「藍牙耳機」)。
- 動態推薦:在商品詳情頁或首頁,用 AJAX 載入「你可能也喜歡」清單。
- 無限滾動:ES 的 scroll API 或 from/size 分頁,支援動態載入。
- 實務案例:蝦皮的搜尋欄支援即時建議,推薦區塊根據瀏覽動態更新。
7. 效能瓶頸與最佳實踐
- 瓶頸:
- 高併發搜尋:ES 叢集負載過高。
- 推薦計算:即時協同過濾耗時。
- 行為收集:高頻事件導致延遲。
- 解決方案:
- 擴展:AWS OpenSearch 部署多節點 ES 叢集,支援 PB 級資料。
- 快取:Redis 儲存熱門查詢與推薦,命中率 >90%。
- 異步:Kafka 處理行為數據,確保高併發。
- 監控:Kibana 追蹤 ES 延遲,Prometheus 監控 Redis/MySQL。
- 成本優化:只索引核心欄位(name、price、category),圖片壓縮至 AWS S3。
- 安全:Laravel Throttle 限制 API 請求,防 SQL 注入與 DDoS。
8. 2025 年趨勢與進階應用
- AI 增強:用 NLP(如 BERT)解析多語言查詢,提升搜尋精準度。
- 元搜尋:聚合蝦皮與其他平台(如 PChome)的商品,實現跨平台比較。
- 即時通知:用 WebSocket 或 LINE API 推送促銷商品,結合 Redis Pub/Sub。
結論與實務建議
蝦皮的快速搜尋與商品推薦系統整合了 Elasticsearch(搜尋)、Redis(快取)、Kafka(行為收集)與協同過濾(推薦)。作為 PHP/Laravel 開發者,你可以:
- 快速上手:用 Docker 部署 Elasticsearch + Redis,測試搜尋與推薦。
- API 設計:用 Laravel 包裝 ES 查詢與 Redis 快取,提供 RESTful 端點。
- 行為追蹤:整合 Kafka 或 RabbitMQ,處理高併發數據。
- 學習資源:閱讀《Elasticsearch: The Definitive Guide》、Redis 官方文件與《Designing Data-Intensive Applications》。
沒有留言:
張貼留言