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"}}}}}
```

  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的混合架构能够发挥各自优势。

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/6775

(0)
Walker的头像Walker
上一篇 2026年3月8日 15:11
下一篇 2026年3月9日 12:56

相关推荐

  • Go工程师体系课 007

    商品微服务 实体结构说明 本模块包含以下核心实体: 商品(Goods) 商品分类(Category) 品牌(Brands) 轮播图(Banner) 品牌分类(GoodsCategoryBrand) 1. 商品(Goods) 描述平台中实际展示和销售的商品信息。 字段说明 字段名 类型 说明 name String 商品名称,必填 brand Pointer …

    后端开发 2026年3月6日
    5800
  • Go工程师体系课 004

    需求分析 后台管理系统 商品管理 商品列表 商品分类 品牌管理 品牌分类 订单管理 订单列表 用户信息管理 用户列表 用户地址 用户留言 轮播图管理 电商系统 登录页面 首页 商品搜索 商品分类导航 轮播图展示 推荐商品展示 商品详情页 商品图片展示 商品描述 商品规格选择 加入购物车 购物车 商品列表 数量调整 删除商品 结算功能 用户中心 订单中心 我的…

    2026年3月6日
    5900
  • 编程基础 0009_testing详解

    Go testing 详解 目录 testing 包基础 表格驱动测试 子测试 t.Run 基准测试 Benchmark 测试覆盖率 TestMain httptest 包 Mock 和接口测试技巧 模糊测试 Fuzz 1. testing 包基础 1.1 测试文件和函数命名规则 Go 测试遵循严格的命名约定: 测试文件以 _test.go 结尾(如 use…

    后端开发 2026年3月6日
    7000
  • Go工程师体系课 007

    商品微服务 实体结构说明 本模块包含以下核心实体: 商品(Goods) 商品分类(Category) 品牌(Brands) 轮播图(Banner) 品牌分类(GoodsCategoryBrand) 1. 商品(Goods) 描述平台中实际展示和销售的商品信息。 字段说明 字段名 类型 说明 name String 商品名称,必填 brand Pointer …

    后端开发 2026年3月7日
    6100
  • Go工程师体系课 012

    Go 中集成 Elasticsearch 1. 客户端库选择 1.1 主流 Go ES 客户端 olivere/elastic:功能最全面,API 设计优雅,支持 ES 7.x/8.x elastic/go-elasticsearch:官方客户端,轻量级,更接近原生 REST API go-elasticsearch/elasticsearch:社区维护的官…

    后端开发 2026年3月7日
    5400
简体中文 繁体中文 English