外观
Elasticsearch 笔记
约 2187 字大约 7 分钟
2025-08-23
一、Elasticsearch 简介
1.1 什么是 Elasticsearch?
Elasticsearch 是一个开源的分布式搜索和分析引擎,基于 Apache Lucene 构建。它能够快速、实时地存储、搜索和分析大量数据。Elasticsearch 通常用于全文搜索、结构化搜索、日志分析、指标监控等场景。
1.2 Elasticsearch 核心特点
- 分布式:自动将数据分片并分布在多个节点上
- 高可用性:通过副本机制保证数据安全和查询可用性
- 近实时搜索:数据索引后几乎可以立即被搜索到
- RESTful API:通过简单的 HTTP 接口进行交互
- 可扩展性:轻松扩展到数百台服务器,处理 PB 级数据
- 多语言支持:支持多种编程语言的客户端
1.3 典型应用场景
- 全文搜索:电商网站商品搜索、内容平台文章搜索
- 日志分析:结合 Logstash 和 Kibana 构成 ELK 栈,进行日志收集和分析
- 实时数据分析:实时监控系统指标、业务数据
- 安全分析:检测异常行为和安全威胁
- 推荐系统:基于用户行为的个性化推荐
二、环境搭建
2.1 安装 Elasticsearch
Docker 安装(推荐):
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.8.0
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:8.8.0Linux 安装:
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.0-linux-x86_64.tar.gz
tar -xzf elasticsearch-8.8.0-linux-x86_64.tar.gz
cd elasticsearch-8.8.0/
bin/elasticsearch2.2 基本概念
| 术语 | 说明 | 类比关系型数据库 |
|---|---|---|
| 索引 (Index) | 一组具有相似特征的文档集合 | 数据库 (Database) |
| 文档 (Document) | 可被索引的基本数据单元,JSON 格式 | 行 (Row) |
| 字段 (Field) | 文档中的属性 | 列 (Column) |
| 映射 (Mapping) | 定义索引中文档的结构和字段类型 | 表结构 (Schema) |
| 分片 (Shard) | 索引的水平切分,提高性能和扩展性 | - |
| 副本 (Replica) | 分片的副本,提供高可用和性能提升 | - |
注意:Elasticsearch 7.x 版本后已移除 Type 概念,一个索引只能包含一种类型的文档。
2.3 基础配置
elasticsearch.yml 关键配置:
# 节点名称
node.name: node-1
# 集群名称
cluster.name: my-application
# 网络绑定
network.host: 0.0.0.0
# HTTP 端口
http.port: 9200
# 初始主节点
cluster.initial_master_nodes: ["node-1"]
# 内存设置
bootstrap.memory_lock: true三、基本操作
3.1 CRUD 操作
创建文档:
POST /users/_doc
{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"created_at": "2023-08-15T10:00:00Z"
}
// 指定ID创建
PUT /users/_doc/1
{
"name": "Jane Smith",
"age": 25
}获取文档:
// 获取指定文档
GET /users/_doc/1
// 搜索所有文档
GET /users/_search
{
"query": {
"match_all": {}
}
}更新文档:
// 全量更新
PUT /users/_doc/1
{
"name": "Jane Smith",
"age": 26,
"email": "jane@example.com"
}
// 部分更新
POST /users/_update/1
{
"doc": {
"age": 27
}
}删除文档:
// 删除单个文档
DELETE /users/_doc/1
// 删除索引中所有文档
POST /users/_delete_by_query
{
"query": {
"match_all": {}
}
}3.2 批量操作
POST /_bulk
{ "index" : { "_index" : "users", "_id" : "2" } }
{ "name" : "Alice", "age" : 28 }
{ "index" : { "_index" : "users", "_id" : "3" } }
{ "name" : "Bob", "age" : 32 }
{ "update" : { "_index" : "users", "_id" : "1" } }
{ "doc" : { "age" : 29 } }
{ "delete" : { "_index" : "users", "_id" : "4" } }四、查询 DSL
4.1 基本查询
// 匹配查询(全文搜索)
GET /users/_search
{
"query": {
"match": {
"name": "John"
}
}
}
// 短语匹配查询
GET /users/_search
{
"query": {
"match_phrase": {
"name": "John Doe"
}
}
}
// 精确值查询
GET /users/_search
{
"query": {
"term": {
"age": 30
}
}
}4.2 复合查询
// bool 查询
GET /users/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "John" } }
],
"filter": [
{ "range": { "age": { "gte": 25, "lte": 35 } } }
],
"must_not": [
{ "term": { "active": false } }
],
"should": [
{ "term": { "vip": true } }
],
"minimum_should_match": 1
}
}
}
// 范围查询
GET /users/_search
{
"query": {
"range": {
"age": {
"gte": 25,
"lte": 35,
"boost": 2.0
}
}
}
}4.3 全文搜索
// 多义词查询
GET /products/_search
{
"query": {
"match": {
"description": {
"query": "quick brown fox",
"analyzer": "english"
}
}
}
}
// 多字段搜索
GET /users/_search
{
"query": {
"multi_match": {
"query": "John",
"fields": ["name", "email"]
}
}
}
// 高亮显示
GET /users/_search
{
"query": {
"match": {
"name": "John"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}五、聚合分析
5.1 指标聚合
// 计算平均年龄
GET /users/_search
{
"size": 0,
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
// 统计最小、最大、平均和总和
GET /users/_search
{
"size": 0,
"aggs": {
"stats_age": {
"stats": {
"field": "age"
}
}
}
}5.2 桶聚合
// 按年龄分组统计
GET /users/_search
{
"size": 0,
"aggs": {
"age_ranges": {
"range": {
"field": "age",
"ranges": [
{ "from": 18, "to": 25 },
{ "from": 25, "to": 35 },
{ "from": 35, "to": 45 }
]
}
}
}
}
// 按字段值分组
GET /users/_search
{
"size": 0,
"aggs": {
"age_groups": {
"terms": {
"field": "age",
"size": 10
}
}
}
}
// 日期直方图
GET /logs/_search
{
"size": 0,
"aggs": {
"logs_over_time": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "day"
}
}
}
}5.3 嵌套聚合
// 先按年龄分组,再计算每组的平均薪资
GET /users/_search
{
"size": 0,
"aggs": {
"age_groups": {
"terms": {
"field": "age",
"size": 10
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
}
}
}六、索引管理
6.1 映射管理
// 创建索引时定义映射
PUT /users
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"age": {
"type": "integer"
},
"email": {
"type": "keyword"
},
"created_at": {
"type": "date"
}
}
}
}
// 动态添加字段映射
PUT /users/_mapping
{
"properties": {
"bio": {
"type": "text"
}
}
}
// 查看映射
GET /users/_mapping6.2 索引模板
// 创建索引模板
PUT /_index_template/users_template
{
"index_patterns": ["users-*"],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
}
}
}
}
}6.3 索引别名
// 创建别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "users-2023",
"alias": "current_users"
}
}
]
}
// 切换别名指向(实现零停机索引切换)
POST /_aliases
{
"actions": [
{
"remove": {
"index": "users-2022",
"alias": "current_users"
}
},
{
"add": {
"index": "users-2023",
"alias": "current_users"
}
}
]
}七、性能优化
7.1 分片策略
- 分片数量:初始分片数应根据数据量和节点数合理规划,一般不超过 1TB/分片
- 副本数量:根据查询负载和高可用需求设置,通常为 1-2 个副本
- 分片分配:合理设置
cluster.routing.allocation参数控制分片分配
推荐分片策略:
- 小型数据集(<1GB):1 个主分片,1 个副本
- 中型数据集(1GB-500GB):3-5 个主分片,1 个副本
- 大型数据集(>500GB):根据数据量和查询负载动态调整
7.2 查询优化
使用 filter 代替 query
{ "query": { "bool": { "filter": [ { "range": { "timestamp": { "gte": "now-1h" } } } ] } } }避免深分页
// 使用 search_after 替代 from + size GET /users/_search { "size": 10, "query": { "match_all": {} }, "sort": [ { "_id": "asc" } ], "search_after": ["last_seen_id"] }控制返回字段
GET /users/_search { "_source": ["name", "age"], "query": { "match_all": {} } }使用批量操作
- 使用
_bulkAPI 替代单个文档操作 - 合理设置批量大小(通常 5-15MB)
- 使用
7.3 内存优化
- 堆内存设置:不超过物理内存的 50%,且不超过 30GB
- 文件系统缓存:留出足够内存供操作系统缓存索引文件
- 避免 fielddata:对 text 类型字段使用 keyword 子字段进行聚合
- 定期优化索引:
POST /index/_forcemerge?max_num_segments=1
八、安全与监控
8.1 安全配置
启用安全功能:
# elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true创建用户:
bin/elasticsearch-users useradd admin -p password -r superuser设置索引权限:
PUT /_security/role/user_reader
{
"indices": [
{
"names": [ "users-*" ],
"privileges": [ "read" ]
}
]
}8.2 监控指标
关键监控指标:
- 集群健康:
GET /_cluster/health - 节点状态:
GET /_nodes/stats - 索引性能:
GET /_stats - 线程池:
GET /_nodes/stats/thread_pool - JVM 状态:
GET /_nodes/stats/jvm
使用 Kibana 监控:
- 安装 Kibana 并连接到 Elasticsearch
- 使用 "Stack Monitoring" 功能监控集群状态
- 创建自定义仪表板监控关键指标
8.3 日志管理
配置日志:
# config/jvm.options
-Dlog4j2.level=INFO
# config/log4j2.properties
appender.rolling.file_name = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}_server
appender.rolling.policies.time_interval = 1
appender.rolling.policies.time_modulate = true常用日志路径:
- 主日志:
logs/elasticsearch.log - 慢查询日志:
logs/elasticsearch_index_search_slowlog.log - GC 日志:
logs/gc.log
九、最佳实践
9.1 索引设计
合理规划索引结构
- 按时间分区:
logs-2023-08-15 - 按业务类型分区:
users,products,orders
- 按时间分区:
字段类型选择
- 精确值查询:
keyword - 全文搜索:
text - 数字范围查询:
integer,long,float,double - 日期:
date
- 精确值查询:
避免映射爆炸
- 限制动态字段数量:
"index.mapping.total_fields.limit": 1000 - 使用
dynamic_templates控制动态映射
- 限制动态字段数量:
9.2 数据导入优化
批量导入
- 使用
_bulkAPI - 批量大小控制在 5-15MB
- 并行导入多个分片
- 使用
临时调整索引设置
PUT /temp_index/_settings { "index": { "refresh_interval": "-1", "number_of_replicas": 0 } } // 导入数据... PUT /temp_index/_settings { "index": { "refresh_interval": "1s", "number_of_replicas": 1 } }使用 reindex API
POST /_reindex { "source": { "index": "old_index" }, "dest": { "index": "new_index" } }
9.3 常见问题解决
问题1:查询性能低下
解决方案:
- 检查是否使用了 filter 上下文
- 避免使用通配符查询
- 减少返回字段数量
- 检查分片数量是否合理
问题2:索引速度慢
解决方案:
- 临时增加刷新间隔
- 减少副本数量
- 调整批量导入大小
- 检查磁盘 I/O 性能
问题3:内存溢出
解决方案:
- 减少 fielddata 使用
- 限制聚合结果数量
- 增加堆内存(不超过 30GB)
- 优化查询避免全扫描
十、实用场景
10.1 日志分析系统
ELK 栈架构:
- 数据采集:Filebeat 收集日志
- 数据处理:Logstash 过滤和转换
- 数据存储:Elasticsearch 索引日志
- 数据可视化:Kibana 创建仪表板
典型查询:
// 查找错误日志
GET /logs-*/_search
{
"query": {
"match": {
"log.level": "ERROR"
}
},
"sort": [
{ "@timestamp": "desc" }
]
}
// 统计每小时错误数量
GET /logs-*/_search
{
"size": 0,
"query": {
"match": {
"log.level": "ERROR"
}
},
"aggs": {
"errors_over_time": {
"date_histogram": {
"field": "@timestamp",
"calendar_interval": "hour"
}
}
}
}10.2 电商搜索系统
商品索引设计:
PUT /products
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"description": {
"type": "text",
"analyzer": "ik_max_word"
},
"price": {
"type": "float"
},
"category": {
"type": "keyword"
},
"tags": {
"type": "keyword"
}
}
}
}搜索实现:
// 商品搜索
GET /products/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "手机",
"fields": ["title^3", "description"]
}
},
"functions": [
{
"field_value_factor": {
"field": "sales",
"factor": 0.1,
"modifier": "log1p"
}
},
{
"gauss": {
"price": {
"origin": "3000",
"scale": "1000"
}
}
}
],
"score_mode": "sum",
"boost_mode": "multiply"
}
}
}升数据搜索和分析的效率和质量。
