Go工程師體系課 009【學習筆記】

其它一些功能

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

拷貝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"}}}}}
<ol>
<li><strong>合理設置分片數量</strong>

分片數量參考公式:
分片數 = 數據量(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的混合架構能夠發揮各自優勢。

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4782

(0)
Walker的頭像Walker
上一篇 2025年11月24日 01:00
下一篇 1天前

相關推薦

  • 熱愛運動,挑戰極限,擁抱自然

    熱愛 在這個快節奏的時代,我們被工作、生活的壓力所包圍,常常忽略了身體的需求。而運動,不僅僅是一種健身方式,更是一種釋放自我、挑戰極限、與自然共舞的生活態度。無論是滑雪、攀岩、衝浪,還是跑步、騎行、瑜伽,每一種運動都能讓我們找到內心的激情,感受到生命的躍動。 運動是一場自我挑戰 挑戰極限,不僅僅是職業運動員的專屬,而是每一個熱愛運動的人都可以追求的目標。它可…

    個人 2025年2月26日
    1.3K00
  • 【開篇】

    我是Walker,生於八十年代初,代碼與生活的旅者。全棧開發工程師,游走於前端與後端的邊界,執著於技術與藝術的交匯點。 代碼,是我編織夢想的語言;項目,是我刻畫未來的畫布。在鍵盤的敲擊聲中,我探索技術的無盡可能,讓靈感在代碼里永恆綻放。 深度咖啡愛好者,迷戀每一杯手衝的詩意與儀式感。在咖啡的醇香與苦澀中,尋找專注與靈感,亦如在開發的世界中追求極致與平衡。 騎…

    2025年2月6日 個人
    2.2K00
  • Go工程師體系課 014【學習筆記】

    rocketmq 快速入門 去我們的各種配置(podman)看是怎麼安裝的 概念介紹 RocketMQ 是阿里開源、Apache 頂級項目的分布式消息中間件,核心組件: NameServer:服務發現與路由 Broker:消息存儲、投遞、拉取 Producer:消息生產者(發送消息) Consumer:消息消費者(訂閱並消費消息) Topic/Tag:主題/…

    個人 2025年11月25日
    16400
  • Go工程師體系課 011【學習筆記】

    查詢的倒排索引 1. 甚麼是倒排索引? 倒排索引(Inverted Index)是一種數據結構,用於快速查找包含特定詞彙的文檔。它是搜索引擎的核心技術之一。 1.1 基本概念 正排索引:文檔 ID → 文檔內容(詞列表) 倒排索引:詞 → 包含該詞的文檔 ID 列表 1.2 為甚麼叫"倒排"? 倒排索引將傳統的"文檔包含哪些詞"的關係倒轉為"詞出現在哪些文檔…

    個人 2025年11月25日
    19900
  • Go工程師體系課 protobuf_guide【學習筆記】

    Protocol Buffers 入門指南 1. 簡介 Protocol Buffers(簡稱 protobuf)是 Google 開發的一種語言無關、平台無關、可擴展的結構化數據序列化機制。與 JSON、XML 等序列化方式相比,protobuf 更小、更快、更簡單。 項目主頁:https://github.com/protocolbuffers/prot…

    個人 2025年11月25日
    1.2K00
簡體中文 繁體中文 English
歡迎🌹 Coding never stops, keep learning! 💡💻 光臨🌹