ElasticSearch性能调优与文档建模最佳实践
- ES底层读写工作原理与性能优化
写入流程与优化
写入步骤:
写入内存缓冲区:文档先写入
Index Buffer。
写入Translog:保证数据持久化(类似数据库WAL日志)。
Refresh:默认每1秒将内存数据生成新的
Segment(可搜索)。
Flush:定期将内存数据持久化到磁盘,清空Translog。
写入优化策略:
增大 refresh_interval:降低刷新频率,减少Segment生成开销。
PUT /my_index/_settings { “index.refresh_interval”: “30s” }
批量写入(Bulk API):减少单次请求开销。
关闭副本:写入时临时关闭副本,完成后再开启。
PUT /my_index/_settings { “index.number_of_replicas”: 0 }
读取流程与优化
查询阶段
:
Query Phase:协调节点将查询分发到各分片,收集结果并排序。
Fetch Phase:根据排序结果获取原始文档数据。
读取优化策略
:
避免深度分页:使用
Scroll 或
Search After。
使用 keyword 类型过滤:精确匹配更快。
启用分片请求缓存:对静态数据开启缓存。
GET /my_index/_search?request_cache=true
- ES数据建模:关联关系处理
嵌套对象(Nested Object)
场景:处理一对多关系,子对象需独立查询。
示例:商品与评论(评论作为嵌套对象)。
PUT /products
{
“mappings”: {
“properties”: {
“comments”: {
“type”: “nested” // 嵌套类型
}
}
}
}
查询:使用
nested 查询隔离父子文档。
GET /products/_search
{
“query”: {
“nested”: {
“path”: “comments”,
“query”: { “term”: { “comments.user”: “Alice” } }
}
}
}
父子关联关系(Parent / Child)
场景:父子文档独立更新,关系松散。
示例:博客文章(Parent)与评论(Child)。
PUT /blogs
{
“mappings”: {
“properties”: {
“blog_id”: { “type”: “keyword” },
“content”: { “type”: “text” },
“comments”: {
“type”: “join”, // 父子关系
“relations”: { “blog”: “comment” }
}
}
}
}
查询:通过
has_child 或
has_parent。
GET /blogs/_search
{
“query”: {
“has_child”: {
“type”: “comment”,
“query”: { “match”: { “text”: “good” } }
}
}
}
- Ingest Pipeline & Painless Script
Ingest Pipeline
用途:在写入前预处理数据(如字段提取、格式转换)。
示例:提取日志中的IP地址并存储到新字段。
PUT _ingest/pipeline/extract_ip
{
“processors”: [
{
“grok”: {
“field”: “message”,
“patterns”: [“%{IP:client_ip}”]
}
}
]
}
Painless Script
用途:动态计算字段或自定义评分逻辑。
示例:动态计算商品折扣价。
POST /products/_update/1
{
“script”: {
“source”: “”"
ctx._source.discount_price =
ctx._source.price * (1 - params.discount);
“”",
“params”: { “discount”: 0.2 }
}
}
- ES数据建模最佳实践
避免动态映射:预定义字段类型,防止自动推断导致性能问题。
扁平化数据结构:减少嵌套层级,提升查询效率。
使用 copy_to 合并字段:优化多字段搜索。
PUT /products
{
“mappings”: {
“properties”: {
“title”: { “type”: “text”, “copy_to”: “full_text” },
“description”: { “type”: “text”, “copy_to”: “full_text” },
“full_text”: { “type”: “text” }
}
}
}
Logstash与FileBeat详解及ELK整合实战
- ELK架构与核心组件
ELK组成:
Logstash:数据采集、过滤、转发。
Elasticsearch:数据存储与检索。
Kibana:数据可视化与分析。
FileBeat角色:轻量级日志采集器,替代Logstash的采集功能,资源占用更低。
- Logstash核心配置与实战
Logstash Pipeline
input {
file {
path => “/var/log/tomcat/*.log”
start_position => “beginning”
}
}
filter {
grok {
match => { “message” => “%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}” }
}
date {
match => [ “timestamp”, “ISO8601” ]
}
}
output {
elasticsearch {
hosts => [“http://es:9200”]
index => “tomcat-logs-%{+YYYY.MM.dd}”
}
}
- FileBeat工作原理与配置
轻量级采集:仅负责日志收集与转发,无复杂处理。
配置示例:
filebeat.inputs:
- type: log
paths:- /var/log/tomcat/*.log
fields:
app: tomcat
output.logstash:
hosts: [“logstash:5044”]
- /var/log/tomcat/*.log
- ELK整合实战
收集Tomcat日志
FileBeat配置:监听Tomcat日志目录,转发到Logstash。
Logstash Pipeline:解析日志字段(如时间戳、错误级别)。
ES索引:按日期生成索引(如 tomcat-logs-2023.10.01)。
收集SkyWalking日志
SkyWalking输出日志到文件,通过FileBeat采集,Logstash解析后写入ES。
亿级流量电商系统高性能搜索实战
- 商品搜索优化策略
分词优化:使用IK分词器,添加自定义业务词库。
相关性调优:结合BM25参数调整(k1和b),提升搜索质量。
聚合分析:按分类、品牌聚合,支持筛选与排序。
- 典型搜索场景实现
示例:多条件筛选与排序
GET /products/_search
{
“query”: {
“bool”: {
“must”: [
{ “match”: { “title”: “手机” } },
{ “term”: { “brand”: “Apple” } }
],
“filter”: [
{ “range”: { “price”: { “gte”: 5000, “lte”: 10000 } } }
]
}
},
“sort”: [
{ “sales”: { “order”: “desc” } }
],
“aggs”: {
“categories”: {
“terms”: { “field”: “category.keyword” }
}
}
}
- 高并发场景优化
读写分离:查询请求路由到副本分片,写入主分片。
缓存策略:使用Redis缓存热点查询结果。
异步写入:通过消息队列(如Kafka)缓冲写入请求。
总结
性能调优:聚焦写入流程(Bulk、Refresh)与查询策略(缓存、分页)。
数据建模:根据场景选择嵌套或父子关系,善用
copy_to 和脚本。
ELK整合:FileBeat轻量采集,Logstash复杂处理,ES高效存储。
电商实战:结合分词、聚合、缓存,实现高并发低延迟搜索。
终极建议:
监控集群健康(如通过Prometheus + Grafana)。
定期执行索引优化(Force Merge、Shrink)。
使用索引生命周期管理(ILM)自动化冷热数据迁移。