Go工程師體系課 009

9次閱讀

其它一些功能

  • 個人中心
  • 收藏
  • 管理收貨地址(增刪改查)
  • 留言

拷貝 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 倍 +

根本原因:

  1. 全表掃描 :LIKE ‘%keyword%’ 無法使用 B + 樹索引,必須掃描所有行
  2. I/ O 密集 :每次查詢都需要從磁盤讀取大量數據
  3. CPU 密集 :對每一行數據進行字符串匹配運算
  4. 內存壓力 :大量數據加載到內存進行處理

實際案例:

某電商平臺商品表有 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                         │
└─────────────────────────────────────┘

相關性因素詳解:

  1. TF(詞頻):關鍵詞在文檔中出現的頻率
  2. IDF(逆文檔頻率):關鍵詞在所有文檔中的稀有程度
  3. 字段長度歸一化 :短字段中的匹配比長字段權重更高
  4. 字段權重 boost:可以設置標題比內容更重要
  5. 查詢時權重 :可以指定某些查詢詞更重要

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 倍提升

實施細節:

  1. 數據同步架構:
    MySQL(主數據) → Binlog → Logstash → Elasticsearch

    定時全量同步(每晚)

  2. 搜索優化策略:

  3. 拼音搜索:支持 “pinguo” 搜索到 “ 蘋果 ”
  4. 同義詞:配置 “ 手機 ”、” 電話 ”、”mobile” 爲同義詞
  5. 搜索建議:實時提示用戶可能的搜索詞
  6. 糾錯功能:自動糾正常見拼寫錯誤

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 查詢性能優化技巧

  1. 使用 Filter 代替 Query(當不需要評分時)
    “`json
    // 優化前:使用 query(計算評分)
    {“query”: {“term”: {“status”: “active”}}}

// 優化後:使用 filter(不計算評分,可緩存)
{“query”: {“bool”: {“filter”: {“term”: {“status”: “active”}}}}}
“`

  1. 合理設置分片數量
    “`
    分片數量參考公式:
    分片數 = 數據量 (GB) / 30GB

示例:
– 100GB 數據:3- 4 個分片
– 1TB 數據:35-40 個分片
“`

  1. 批量操作優化
    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 可以:

  1. 提升搜索性能 :從秒級降到毫秒級
  2. 改善搜索質量 :通過相關性評分和智能分詞
  3. 支持複雜分析 :實時聚合和統計分析
  4. 降低運維成本 :更少的服務器,更高的效率

但需要注意的是,Elasticsearch 不是 MySQL 的替代品,而是補充。在實際項目中,應該根據具體場景選擇合適的存儲方案,通常採用 MySQL+Elasticsearch 的混合架構能夠發揮各自優勢。

正文完
 0