其它一些功能
- 個人中心
- 收藏
- 管理收貨地址(增刪改查)
- 留言
拷貝
inventory_srv–>userop_srv查詢替換所有的inventory
Elasticsearch 深度解析文檔
1. 什麼是 Elasticsearch
Elasticsearch 是一個基於 Apache Lucene 構建的分佈式、RESTful 搜索和分析引擎,能夠快速地存儲、搜索和分析海量數據。它是 Elastic Stack(原 ELK Stack)的核心組件。
2. MySQL 搜索面臨的問題 – 深度剖析
2.1 性能低下問題詳解
問題現象:
-- 當數據量達到 100 萬條時,以下查詢可能需要數秒
SELECT * FROM products WHERE name LIKE '% 手機 %' OR description LIKE '% 手機 %';
性能對比數據:
| 數據量級 | MySQL LIKE 查詢 | Elasticsearch 全文搜索 | 性能提升 |
|---|---|---|---|
| 1 萬條 | 50ms | 10ms | 5 倍 |
| 10 萬條 | 500ms | 15ms | 33 倍 |
| 100 萬條 | 5000ms | 20ms | 250 倍 |
| 1000 萬條 | 50000ms+ | 30ms | 1600 倍 + |
根本原因:
- 全表掃描 :LIKE ‘%keyword%’ 無法使用 B + 樹索引,必須掃描所有行
- I/ O 密集 :每次查詢都需要從磁盤讀取大量數據
- CPU 密集 :對每一行數據進行字符串匹配運算
- 內存壓力 :大量數據加載到內存進行處理
實際案例:
某電商平臺商品表有 500 萬條記錄,使用 MySQL 模糊查詢搜索 ” 蘋果手機 ”:
– 查詢時間:8.3 秒
– CPU 使用率:飆升至 85%
– 併發 10 個查詢時,響應時間增長到 30 秒以上
2.2 沒有相關性排名問題詳解
MySQL 查詢結果的痛點:
-- MySQL 只能按固定規則排序
SELECT * FROM products
WHERE name LIKE '% 手機 %'
ORDER BY price DESC; -- 只能按價格、時間等字段排序
Elasticsearch 的相關性評分機制:
搜索詞:" 小米手機 "
相關性評分計算:┌─────────────────────────────────────┐
│ 文檔 1:" 小米手機 12 Pro" │
│ • 詞頻 (TF):2 個關鍵詞都出現 │
│ • 逆文檔頻率 (IDF):計算詞的稀有度 │
│ • 字段長度:標題較短,權重更高 │
│ • 評分:9.8 │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 文檔 2:" 這是一款性價比很高的手機 " │
│ • 詞頻 (TF):只有 " 手機 " 出現 │
│ • 逆文檔頻率 (IDF):" 手機 " 較常見 │
│ • 字段長度:描述較長,權重降低 │
│ • 評分:3.2 │
└─────────────────────────────────────┘
相關性因素詳解:
- TF(詞頻):關鍵詞在文檔中出現的頻率
- IDF(逆文檔頻率):關鍵詞在所有文檔中的稀有程度
- 字段長度歸一化 :短字段中的匹配比長字段權重更高
- 字段權重 boost:可以設置標題比內容更重要
- 查詢時權重 :可以指定某些查詢詞更重要
2.3 無法全文搜索問題詳解
MySQL 全文索引的侷限:
-- MySQL 全文索引創建
ALTER TABLE products ADD FULLTEXT(name, description);
-- 問題 1:最小詞長限制(默認 4 個字符)-- " 手機 " 可以搜索,但 " 機 " 搜不到
-- 問題 2:中文分詞支持差
-- " 蘋果手機 " 被當作一個整體,搜索 " 蘋果 " 找不到
Elasticsearch 全文搜索能力:
// ES 的分析過程示例
輸入文本:" 我想買一臺蘋果手機 "
分詞結果:[我] [想] [買] [一臺] [蘋果] [手機] [蘋果手機]
同義詞擴展:[蘋果] → [Apple, iPhone]
[手機] → [手機, 電話, mobile]
拼寫糾錯:" 蘋果手擊 " → 建議 " 蘋果手機 "
2.4 搜索不準確、沒有分詞問題詳解
MySQL 字符串匹配的問題:
-- 搜索 " 筆記本 "
SELECT * FROM products WHERE name LIKE '% 筆記本 %';
-- 結果:能找到 " 筆記本電腦 "
-- 問題:找不到 " 筆記 本子 "、"notebook"、" 手提電腦 "
Elasticsearch 智能分詞過程:
原始文本:"ThinkPad X1 Carbon 超輕薄筆記本電腦 "
標準分詞器:[ThinkPad] [X1] [Carbon] [超輕薄] [筆記本] [電腦]
IK 分詞器(中文):[ThinkPad] [X1] [Carbon] [超] [輕薄] [超輕薄]
[筆記] [本] [筆記本] [電腦] [筆記本電腦]
拼音分詞器:[si] [kao] [pad] → 可以通過拼音搜索
N-gram 分詞:[Thi] [hin] [ink] [nkP] → 支持部分匹配
3. 什麼是全文搜索 – 核心原理解析
3.1 結構化數據 vs 非結構化數據
結構化數據(MySQL 存儲方式):┌──────┬────────┬────────┬────────┐
│ ID │ Name │ Price │ Stock │
├──────┼────────┼────────┼────────┤
│ 1 │iPhone │ 5999 │ 100 │
│ 2 │ 小米 │ 2999 │ 200 │
└──────┴────────┴────────┴────────┘
非結構化數據(文本內容):" 這款 iPhone 手機採用 A15 處理器,性能強勁,拍照效果出色,續航能力提升 20%,用戶評價:'太棒了,物超所值!'"
3.2 倒排索引原理詳解
正排索引(MySQL):
文檔 ID → 內容
Doc1 → " 小米手機 "
Doc2 → " 蘋果手機 "
Doc3 → " 小米電視 "
倒排索引(Elasticsearch):
詞項 → 文檔列表
" 小米 " → [Doc1, Doc3]
" 手機 " → [Doc1, Doc2]
" 蘋果 " → [Doc2]
" 電視 " → [Doc3]
搜索 " 小米手機 ":1. 查找 " 小米 " → 得到 [Doc1, Doc3]
2. 查找 " 手機 " → 得到 [Doc1, Doc2]
3. 計算交集 → Doc1(最相關)
3.3 倒排索引的詳細結構
完整的倒排索引結構:詞項:" 手機 "
├── 文檔頻率 (DF):1000 個文檔包含此詞
├── 倒排列表:│ ├── Doc1:│ │ ├── 詞頻 (TF):3 次
│ │ ├── 位置:[5, 28, 102]
│ │ └── 字段:[title, description]
│ ├── Doc2:│ │ ├── 詞頻 (TF):1 次
│ │ ├── 位置:[15]
│ │ └── 字段:[title]
│ └── ...
└── 統計信息:最高詞頻、平均詞頻等
4. Elasticsearch 架構詳解
4.1 集羣架構
Elasticsearch 集羣架構圖:┌─────────────── ES Cluster ──────────────┐
│ │
│ ┌─────────────────────────────────┐ │
│ │ Master Node (主節點) │ │
│ │ • 集羣管理 │ │
│ │ • 索引創建 / 刪除 │ │
│ │ • 分片分配 │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Data │ │ Data │ │
│ │ Node 1 │ │ Node 2 │ │
│ │ ┌──────┐ │ │ ┌──────┐ │ │
│ │ │ P0 │ │ │ │ R0 │ │ │
│ │ ├──────┤ │ │ ├──────┤ │ │
│ │ │ R1 │ │ │ │ P1 │ │ │
│ │ └──────┘ │ │ └──────┘ │ │
│ └──────────┘ └──────────┘ │
│ │
│ P = Primary Shard (主分片) │
│ R = Replica Shard (副本分片) │
└─────────────────────────────────────────┘
4.2 數據寫入流程
寫入流程詳解:客戶端 → 協調節點 → 主分片 → 副本分片
1. 客戶端發送寫請求
↓
2. 協調節點通過 hash 路由確定分片
↓
3. 請求轉發到主分片節點
↓
4. 主分片寫入成功
↓
5. 並行複製到副本分片
↓
6. 所有副本確認
↓
7. 返回成功響應給客戶端
時間線:T0 ──→ T1 ──→ T2 ──→ T3 ──→ T4
接收 路由 主分片 副本 響應
4.3 查詢流程
查詢執行過程:Phase 1: Query(查詢階段)┌─────────────────────────────────┐
│ 協調節點向所有分片發送查詢請求 │
│ 每個分片返回 Top N 的文檔 ID 和分數 │
└─────────────────────────────────┘
↓
Phase 2: Fetch(獲取階段)┌─────────────────────────────────┐
│ 協調節點整合所有結果並排序 │
│ 獲取最終需要的文檔完整內容 │
└─────────────────────────────────┘
5. Elasticsearch 核心功能詳解
5.1 查詢類型詳解
// 1. Match 查詢 - 全文搜索
{
"query": {
"match": {
"title": {
"query": " 蘋果手機 ",
"operator": "and" // 必須包含所有詞
}
}
}
}
// 2. Term 查詢 - 精確匹配
{
"query": {
"term": {"category.keyword": " 手機 " // 不分詞,精確匹配}
}
}
// 3. Range 查詢 - 範圍查詢
{
"query": {
"range": {
"price": {
"gte": 1000,
"lte": 5000
}
}
}
}
// 4. Bool 複合查詢
{
"query": {
"bool": {
"must": [{"match": {"title": " 手機 "}}
],
"filter": [{"range": {"price": {"lte": 5000}}}
],
"should": [{"match": {"brand": " 蘋果 "}} // 加分項
],
"must_not": [{"term": {"status": "discontinued"}}
]
}
}
}
5.2 聚合分析功能
// 銷售數據分析示例
{
"aggs": {
"sales_per_category": {
"terms": {"field": "category"},
"aggs": {
"avg_price": {
"avg": {"field": "price"}
},
"total_sales": {
"sum": {"field": "sales_count"}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [{"to": 1000},
{"from": 1000, "to": 5000},
{"from": 5000}
]
}
}
}
}
}
}
6. 實際應用案例分析
6.1 電商搜索優化案例
某電商平臺搜索優化前後對比:
| 指標 | MySQL 方案 | Elasticsearch 方案 | 改善效果 |
|---|---|---|---|
| 平均搜索耗時 | 2.3 秒 | 0.05 秒 | 46 倍提升 |
| 搜索準確率 | 65% | 92% | 提升 27% |
| 零結果率 | 18% | 3% | 降低 15% |
| 服務器數量 | 8 臺 | 3 臺 | 節省 62.5% 成本 |
| 併發能力 | 100 QPS | 5000 QPS | 50 倍提升 |
實施細節:
-
數據同步架構:
MySQL(主數據) → Binlog → Logstash → Elasticsearch
↓
定時全量同步(每晚) -
搜索優化策略:
- 拼音搜索:支持 “pinguo” 搜索到 “ 蘋果 ”
- 同義詞:配置 “ 手機 ”、” 電話 ”、”mobile” 爲同義詞
- 搜索建議:實時提示用戶可能的搜索詞
- 糾錯功能:自動糾正常見拼寫錯誤
6.2 日誌分析系統案例
某互聯網公司日誌分析系統:
日誌處理流程:應用服務器 → Filebeat → Logstash → Elasticsearch → Kibana
↓ ↓ ↓ ↓ ↓
產生日誌 收集 處理轉換 存儲索引 可視化展示
處理規模:• 日誌量:每天 100GB
• 日誌條數:10 億條 / 天
• 查詢響應:毫秒級
• 保存週期:30 天熱數據,1 年冷數據
7. 性能優化最佳實踐
7.1 索引設計優化
// 優化的 Mapping 設計
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": {"type": "keyword" // 支持精確匹配},
"pinyin": {
"type": "text",
"analyzer": "pinyin" // 支持拼音搜索
}
}
},
"price": {
"type": "scaled_float",
"scaling_factor": 100 // 價格精度優化
},
"category": {"type": "keyword" // 分類不需要分詞},
"description": {
"type": "text",
"analyzer": "ik_smart"
},
"created_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis"
}
}
}
}
7.2 查詢性能優化技巧
- 使用 Filter 代替 Query(當不需要評分時)
“`json
// 優化前:使用 query(計算評分)
{“query”: {“term”: {“status”: “active”}}}
// 優化後:使用 filter(不計算評分,可緩存)
{“query”: {“bool”: {“filter”: {“term”: {“status”: “active”}}}}}
“`
- 合理設置分片數量
“`
分片數量參考公式:
分片數 = 數據量 (GB) / 30GB
示例:
– 100GB 數據:3- 4 個分片
– 1TB 數據:35-40 個分片
“`
- 批量操作優化
json
// 使用 bulk API 批量索引
POST _bulk
{"index": {"_index": "products", "_id": 1}}
{"name": "iPhone", "price": 5999}
{"index": {"_index": "products", "_id": 2}}
{"name": "小米", "price": 2999}
8. Elasticsearch vs 傳統數據庫
8.1 適用場景對比
| 場景 | MySQL | Elasticsearch | 推薦選擇 |
|---|---|---|---|
| 全文搜索 | ❌ 差 | ✅ 優秀 | ES |
| 事務支持 | ✅ 完整 ACID | ❌ 無事務 | MySQL |
| 實時統計分析 | ⚠️ 一般 | ✅ 優秀 | ES |
| 關係查詢 | ✅ 優秀 | ❌ 有限 | MySQL |
| 地理位置搜索 | ❌ 差 | ✅ 優秀 | ES |
| 日誌分析 | ❌ 不適合 | ✅ 專長 | ES |
| 精確數值計算 | ✅ 精確 | ⚠️ 近似 | MySQL |
8.2 混合架構方案
推薦的混合架構:用戶請求
↓
┌──────────────┐
│ 應用層 │
└──────────────┘
↓
┌──────────────────────────┐
│ 搜索請求 → ES │
│ 事務操作 → MySQL │
│ 緩存 → Redis │
└──────────────────────────┘
數據同步:MySQL(寫) → Binlog → Canal/Debezium → Kafka → ES(讀)
9. 常見問題與解決方案
9.1 數據一致性問題
問題: MySQL 和 ES 數據不一致
解決方案:
1. 雙寫策略 :同時寫 MySQL 和 ES,使用消息隊列保證最終一致性
2. CDC(Change Data Capture):通過 Binlog 實時同步
3. 定期校驗 :定時任務對比數據差異並修復
9.2 深度分頁問題
問題: 查詢第 10000 頁數據時性能極差
解決方案:
// 1. 使用 search_after(推薦){
"size": 10,
"sort": [{"_id": "asc"}],
"search_after": [10000] // 上一頁最後一個文檔的 sort 值
}
// 2. 使用 scroll API(適合導出)POST /products/_search?scroll=1m
{
"size": 100,
"query": {"match_all": {}}
}
10. 總結
Elasticsearch 通過倒排索引、分佈式架構和強大的全文搜索能力,完美解決了傳統數據庫在搜索場景下的各種問題。合理使用 Elasticsearch 可以:
- 提升搜索性能 :從秒級降到毫秒級
- 改善搜索質量 :通過相關性評分和智能分詞
- 支持複雜分析 :實時聚合和統計分析
- 降低運維成本 :更少的服務器,更高的效率
但需要注意的是,Elasticsearch 不是 MySQL 的替代品,而是補充。在實際項目中,應該根據具體場景選擇合適的存儲方案,通常採用 MySQL+Elasticsearch 的混合架構能夠發揮各自優勢。