其它一些功能
- 个人中心
- 收藏
- 管理收货地址(增删改查)
- 留言
拷贝
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://joyjs.cn/archives/4782