文章目录
为什么我的数据库扛不住百万数据?(灵魂拷问)
你是不是也经历过这样的绝望时刻?当产品经理兴奋地说"我们要做全站模糊搜索"时,MySQL的LIKE查询直接把数据库CPU干到100%!(别问我怎么知道的)这个时候就该ElasticSearch登场了!这个基于Lucene的分布式搜索引擎,处理起海量数据就像吃豆人吞豆子一样轻松(实测单节点就能轻松应对TB级数据)。
十分钟快速上手指南
1. 环境准备(避坑预警)
# 使用Docker快速部署(生产环境建议配置集群)
docker run -d --name elasticsearch \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
elasticsearch:8.11.4
!!!注意:默认内存设置可能不够用,修改jvm.options
中的-Xms和-Xmx值(建议不超过物理内存的50%)
2. 索引创建的艺术
PUT /product_index
{
"mappings": {
"properties": {
"product_name": { "type": "text", "analyzer": "ik_max_word" },
"price": { "type": "double" },
"tags": { "type": "keyword" },
"description": { "type": "text", "analyzer": "ik_smart" }
}
}
}
(划重点)中文搜索必须用IK分词器!官方自带的分词器会把"中华人民共和国"拆成7个字,而IK能正确识别为词组。
3. 数据导入的骚操作
用Bulk API批量导入数据时,记得控制每次请求的文档数量(建议500-1000条/次)。曾经有个同事一次性导入10万条数据,直接把ES搞崩了(别学他)!
实战:电商搜索功能开发
场景需求拆解
- 多字段匹配(商品名+描述)
- 价格区间过滤
- 标签精确匹配
- 结果按销量排序
GET /product_index/_search
{
"query": {
"bool": {
"must": [
{ "match": {
"product_name": "无线蓝牙耳机"
}}
],
"filter": [
{ "range": { "price": { "gte": 100, "lte": 500 } }},
{ "term": { "tags": "限时折扣" }}
]
}
},
"sort": [
{ "sales_volume": "desc" }
]
}
高亮显示技巧
在查询中添加:
"highlight": {
"fields": {
"product_name": {},
"description": {}
},
"pre_tags": ["<em class='highlight'>"],
"post_tags": ["</em>"]
}
这样搜索结果中的关键词会被自动包裹,前端同学会爱死你的!
性能调优三板斧
1. 分片设置玄学
- 每个分片大小控制在30-50GB
- 分片数 = 数据总量 / 单分片容量
- 主分片数一旦创建不可修改!(重要的事情说三遍)
2. 冷热数据分离
使用ILM(索引生命周期管理)自动迁移旧数据到冷节点,硬件成本直降60%!具体操作:
- 定义Hot/Warm节点角色
- 创建生命周期策略
- 应用策略到索引
3. 查询优化黑魔法
- 多用filter少用query(filter有缓存!)
- 避免深度分页(用search_after替代)
- 聚合查询开启
execution_hint: map
我踩过的那些坑(血泪史)
脑裂问题
某次网络波动导致集群出现两个master节点,数据写入乱套了。解决方案:
- 设置
discovery.zen.minimum_master_nodes = (master节点数/2)+1
- 启用
gateway.recover_after_nodes
配置
字段类型陷阱
曾经把时间戳设为text类型,范围查询直接崩了。切记:
- 数值型字段用long/double
- 时间用date类型
- 需要精确匹配的用keyword
监控与报警配置
推荐组合拳:
- Prometheus + Grafana 监控集群健康
- Cerebro工具实时查看节点状态
- 设置报警规则(比如JVM内存超70%立即报警)
# 示例报警规则
alert: ES_JVM_Memory_High
expr: es_jvm_memory_usage_percent > 70
for: 5m
labels:
severity: critical
annotations:
summary: "ES节点内存告警 (实例 {{ $labels.instance }})"
description: "JVM内存使用率已达{{ $value }}%,请立即处理!"
总结:什么时候该用ES?
经过多个项目实战,我的经验是:
✅ 需要模糊搜索/相关性排序
✅ 日志分析类场景
✅ 实时数据分析
❌ 强事务要求的场景(还是用回你的MySQL吧)
最后送大家一句话:ES不是银弹,但用对了地方绝对能让你体验飞一般的感觉!下次遇到产品经理提搜索需求时,记得挺直腰板说:“这个需求,接得住!”