其它一些功能
- 個人中心
- 收藏
- 管理收貨地址(增刪改查)
- 留言
拷貝
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"}}}}}
<ol>
<li><strong>合理設置分片數量</strong>
分片數量參考公式:
分片數 = 數據量(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的混合架構能夠發揮各自優勢。
主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4782