一、什么是 Elasticsearch (ES)
Elasticsearch 是一款基于 Lucene 构建的开源、分布式、RESTful 风格的搜索引擎,核心定位是解决“快速查找数据”的问题,尤其擅长非结构化文本检索,比数据库的 LIKE 语句快数十倍。
其核心特点如下:
-
分布式:自动分片存储数据,支持水平扩展,轻松应对海量数据
-
实时性:近实时(NRT)索引和搜索,数据写入后秒级可查
-
全文检索:支持复杂的文本检索、模糊匹配、高亮等功能
-
易扩展:与 Kibana、Logstash 组成 ELK 栈(现 Elastic Stack),适用于日志分析、监控、全文检索等场景
-
REST API:通过 HTTP 请求即可完成所有操作,支持多种编程语言客户端(Java/Python/Go 等)
二、ES 安装步骤(Linux 环境)
2.1 前置条件
-
安装 JDK 11+(ES 7.x+ 推荐 JDK 11,8.x+ 支持 JDK 17)
-
禁用系统 Swap 分区(避免性能损耗)
-
调整系统文件描述符限制(建议至少 65535)
2.2 具体步骤
1. 下载并解压 ES 安装包
下载(以 8.14.0 为例)
wget artifacts.elastic.co/downloads/e…
解压
tar -zxvf elasticsearch-8.14.0-linux-x86_64.tar.gz cd elasticsearch-8.14.0
2. 修改系统配置(解决权限/性能问题)
1. 修改系统限制(临时生效,永久生效需修改 /etc/security/limits.conf)
ulimit -n 65535 ulimit -u 4096
2. 禁止 ES 使用 root 用户运行(创建专用用户)
useradd esuser chown -R esuser:esuser elasticsearch-8.14.0
3. 配置 ES 核心参数(config/elasticsearch.yml)
基本配置
cluster.name: my-es-cluster # 集群名称(同一集群需一致) node.name: node-1 # 节点名称(每个节点唯一) path.data: /data/es/data # 数据存储路径 path.logs: /data/es/logs # 日志存储路径 network.host: 0.0.0.0 # 监听地址(0.0.0.0 允许外部访问) http.port: 9200 # HTTP 端口 discovery.seed_hosts: ["127.0.0.1"] # 集群节点列表 cluster.initial_master_nodes: ["node-1"] # 初始主节点
关闭安全功能(测试用,生产环境必须开启)
xpack.security.enabled: false xpack.security.enrollment.enabled: false
4. 启动 ES
切换到 esuser 用户
su esuser
启动(前台运行,测试用)
./bin/elasticsearch
后台启动(生产环境)
./bin/elasticsearch -d
验证启动成功(返回 JSON 表示正常)
5. 常见启动问题解决
-
权限不足:确保数据/日志目录归 esuser 所有
-
内存不足:修改
config/jvm.options,降低堆内存(如Xms512m -Xmx512m) -
端口被占用:修改
http.port为其他端口(如 9201)
三、ES 核心关键字段说明
3.1 集群/节点相关字段
| 字段 | 说明 | 示例 |
|------|------|------|
| cluster.name | 集群名称(同一集群必须一致) | my-es-cluster |
| node.name | 节点名称(唯一标识节点) | node-1 |
| node.master | 是否允许成为主节点 | true/false |
| node.data | 是否存储数据(数据节点) | true/false |
| network.host | 监听地址 | 0.0.0.0(允许所有IP访问) |
3.2 索引(Index)核心字段
| 字段 | 说明 | 示例 |
|------|------|------|
| index.name | 索引名称(类似数据库表名) | user_info |
| index.number_of_shards | 分片数(创建后不可修改) | 3(建议等于节点数) |
| index.number_of_replicas | 副本数(可动态修改) | 1(每个分片1个副本) |
| index.refresh_interval | 刷新间隔(控制实时性) | 1s(秒级刷新)/-1(关闭自动刷新) |
3.3 映射(Mapping)核心字段
Mapping 类似数据库的「表结构」,定义字段类型和属性:
| 字段/属性 | 说明 | 常用类型 |
|-----------|------|----------|
| type | 字段类型 | text(全文检索)、keyword(精确匹配)、integer(整数)、date(日期)、object(嵌套对象) |
| analyzer | 分词器(仅 text 类型) | ik_max_word(IK中文分词)、standard(默认英文分词) |
| index | 是否创建索引(可搜索) | true(默认)/false(仅存储不检索) |
| doc_values | 是否启用列存储(排序/聚合用) | true(默认)/false |
| fielddata | text 类型是否允许排序/聚合 | false(默认,需手动开启) |
| format | 日期格式 | yyyy-MM-dd HH:mm:ss |
3.4 文档(Document)核心字段
| 字段 | 说明 | 示例 |
|------|------|------|
| _id | 文档唯一ID(类似主键) | 自动生成/手动指定(如 1001) |
| _index | 文档所属索引 | user_info |
| _type | 文档类型(7.x+ 仅支持 _doc) | _doc |
| _source | 文档原始数据(JSON格式) | {"name":"张三","age":25} |
| _score | 搜索相关性得分(越高越匹配) | 1.234 |
四、ES 基础命令示例(REST API)
4.1 集群/节点状态查询
查询集群健康状态(green/黄色/red)
curl -X GET "http://localhost:9200/_cat/health?v"
查询所有节点信息
curl -X GET "http://localhost:9200/_cat/nodes?v"
查询集群所有索引
curl -X GET "http://localhost:9200/_cat/indices?v"
4.2 索引操作
1. 创建索引(指定分片/副本)
curl -X PUT "http://localhost:9200/user_info" -H "Content-Type: application/json" -d '{ "settings": { "number_of_shards": 3, "number_of_replicas": 1, "refresh_interval": "1s" }, "mappings": { "properties": { "name": {"type": "text", "analyzer": "ik_max_word"}, # 中文分词 "age": {"type": "integer"}, "phone": {"type": "keyword"}, # 精确匹配(不分词) "create_time": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"} } } }'
2. 查询索引结构
curl -X GET "http://localhost:9200/user_info/_mapping?pretty"
3. 修改索引副本数(动态调整)
curl -X PUT "http://localhost:9200/user_info/_settings" -H "Content-Type: application/json" -d '{ "number_of_replicas": 2 }'
4. 删除索引
curl -X DELETE "http://localhost:9200/user_info"
4.3 文档操作(CRUD)
1. 添加文档(手动指定ID)
curl -X PUT "http://localhost:9200/user_info/_doc/1001" -H "Content-Type: application/json" -d '{ "name": "张三", "age": 25, "phone": "13800138000", "create_time": "2024-01-01 10:00:00" }'
2. 添加文档(自动生成ID)
curl -X POST "http://localhost:9200/user_info/_doc" -H "Content-Type: application/json" -d '{ "name": "李四", "age": 30, "phone": "13900139000", "create_time": "2024-01-02 11:00:00" }'
3. 查询文档(按ID)
curl -X GET "http://localhost:9200/user_info/_doc/1001?pretty"
4. 更新文档(全量更新)
curl -X PUT "http://localhost:9200/user_info/_doc/1001" -H "Content-Type: application/json" -d '{ "name": "张三", "age": 26, # 仅修改年龄 "phone": "13800138000", "create_time": "2024-01-01 10:00:00" }'
5. 局部更新文档(推荐)
curl -X POST "http://localhost:9200/user_info/_update/1001" -H "Content-Type: application/json" -d '{ "doc": {"age": 27} }'
6. 删除文档
curl -X DELETE "http://localhost:9200/user_info/_doc/1001"
4.4 基础搜索命令
1. 匹配所有文档(分页:from=起始位置,size=条数)
curl -X GET "http://localhost:9200/user_info/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "match_all": {} }, "from": 0, "size": 10 }'
2. 全文检索(匹配name中包含"张"的文档)
curl -X GET "http://localhost:9200/user_info/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "match": { "name": "张" } } }'
3. 精确匹配(keyword类型字段)
curl -X GET "http://localhost:9200/user_info/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "term": { "phone": "13800138000" } } }'
4. 范围查询(age大于25小于30)
curl -X GET "http://localhost:9200/user_info/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "range": { "age": { "gt": 25, "lt": 30 } } } }'
5. 组合查询(must=且,should=或,must_not=非)
curl -X GET "http://localhost:9200/user_info/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "bool": { "must": [ {"match": {"name": "张"}}, {"range": {"age": {"gte": 25}}} ], "must_not": [ {"term": {"phone": "13900139000"}} ] } } }'
4.5 批量操作(Bulk)
批量添加/更新/删除文档(格式:操作行 + 数据行)
curl -X POST "http://localhost:9200/_bulk?pretty" -H "Content-Type: application/json" -d ' {"index":{"_index":"user_info","_id":"1002"}} {"name":"王五","age":28,"phone":"13700137000","create_time":"2024-01-03 12:00:00"} {"update":{"_index":"user_info","_id":"1001"}} {"doc":{"age":28}} {"delete":{"_index":"user_info","_id":"1003"}} '
五、分词器 & 倒排索引
5.1 分词器(Analyzer)
1. 定义
分词器 = 把一段文本,切分成一个个“关键词”的工具。ES 底层是 Lucene,所有文本搜索,都依赖分词,分词的质量直接决定搜索效果。
2. 分词器组成
一个完整的分词器由 3 部分组成,按执行顺序依次是:
-
Character Filter(字符过滤):预处理文本,去掉 HTML 标签、特殊符号、表情等无关内容,比如将 `我喜欢ES
-
Tokenizer(分词器):核心步骤,按预设规则把预处理后的句子切分成独立的“词元”,比如将
我喜欢使用elasticsearch切分成多个词。 -
Token Filter(词过滤):对词元进行优化处理,常见操作包括转小写、去除停用词(的、了、是、a、the 等无意义词汇)、同义词替换(如“ES”替换为“Elasticsearch”)。
3. ES 内置分词器
-
standard:ES 默认分词器,英文按空格、标点切分,中文按单字切分(不适合中文检索)。 -
simple:按非字母字符切分,同时将所有字母转为小写,适合简单的英文检索。 -
whitespace:仅按空格切分,不做其他处理,保留原始大小写和符号。 -
ik_smart/ik_max_word:中文分词必备(需额外安装 IK 分词器插件),专门适配中文语义。
4. 中文为什么必须用 IK 分词器?
ES 内置分词器对中文的处理的是“单字分词”,无法满足中文检索需求,对比示例如下:
-
默认 standard 分词:
我喜欢使用elasticsearch→我喜欢使用elasticsearch,搜索“喜欢”无法命中该文档。 -
IK 分词器:
我喜欢使用elasticsearch→我喜欢使用elasticsearch,搜索“喜欢”“使用”均可精准命中。
IK 分词器的两种核心模式:
-
ik_smart:粗分模式,速度快,仅切分最核心的词汇(如中华人民共和国→中华人民共和国)。 -
ik_max_word:细粒度拆分模式,将句子拆分成所有可能的词汇(如中华人民共和国→中华人民共和国中华人民中华人民共和国),搜索更全面。
5.2 倒排索引(Inverted Index)
1. 定义
倒排索引 = 关键词 → 文档ID 的映射关系,是 ES 能实现“秒级搜索海量数据”的核心原理,也是搜索引擎的基础。
简单来说,倒排索引不存储“文档包含哪些内容”,而是存储“每个关键词出现在哪些文档中”,通过关键词快速定位文档,而非遍历所有文档。
2. 对比:正排索引 vs 倒排索引
① 正排索引(数据库 LIKE 检索方式)
核心逻辑:文档 → 内容,即存储每个文档的完整内容,检索时需遍历所有文档,逐行匹配关键词。
示例(3条文档):
文档1:我喜欢Java 文档2:我喜欢ES 文档3:ES非常快
检索“喜欢”:遍历3条文档,逐行判断是否包含“喜欢” → 效率极低,数据量越大,检索越慢。
② 倒排索引(ES 检索方式)
核心逻辑:关键词 → 文档ID,即先对所有文档的内容分词,再建立“关键词”与“包含该关键词的文档ID”的映射。
基于上面3条文档,建立的倒排索引如下:
我 → [1,2] 喜欢 → [1,2] Java → [1] ES → [2,3] 非常 → [3] 快 → [3]
检索“喜欢”:直接查询关键词“喜欢”,获取对应的文档ID [1,2],无需遍历所有文档 → 秒级出结果。
3. 倒排索引核心流程
-
文档写入 ES,触发分词操作(通过分词器将文档文本切分为关键词);
-
建立“关键词 → 文档ID”的映射关系,同时记录关键词在文档中的出现位置、频率(用于计算搜索相关性得分
_score); -
用户发起搜索请求,输入的搜索词先经过分词处理;
-
ES 查询倒排索引,根据关键词快速定位对应的文档ID;
-
返回文档内容,并根据相关性得分排序,呈现搜索结果。
4. 倒排索引优点
-
检索速度极快:无需扫全表,通过关键词直接定位文档,适配海量数据检索;
-
支持多种检索场景:模糊匹配、前缀匹配、通配符匹配、高亮显示等;
-
天然适配全文检索:完美结合分词器,解决非结构化文本的检索难题。
六、优化建议
-
分词器优化:中文检索必须安装 IK 分词器(插件地址:github.com/medcl/elast…
-
索引规划:
-
分片数:建议等于节点数(如 3 节点设置 3 分片),避免分片过多(增加集群开销)或过少(无法充分利用节点资源);
-
副本数:生产环境至少设置 1 个副本,保证集群高可用(某节点故障时,副本可替代主分片提供服务)。
-
-
性能优化:
-
批量写入:使用 Bulk API 代替单条写入,大幅提升数据导入效率;
-
刷新间隔:批量导入数据时,临时设置
index.refresh_interval: -1(关闭自动刷新),导入完成后恢复为1s,减少刷新开销; -
字段类型:无需检索的字段(如备注、附件路径)设置
index: false,减少索引存储和检索开销;text 类型字段尽量不用于排序/聚合,如需排序可使用 keyword 子字段。
-
- 监控与维护:通过 Kibana 监控集群状态(CPU、内存、磁盘使用率、分片健康度),定期清理过期索引,避免磁盘溢出。
七、总结
-
ES 核心定位:分布式实时搜索引擎,基于 Lucene 构建,擅长全文检索和海量数据快速查询,提供 REST API 便于开发调用。
-
核心概念:索引(类似数据库表)、分片(数据拆分存储)、映射(字段结构定义)、文档(单条数据)是 ES 最基础的核心概念,需熟练掌握。
-
核心原理:分词器决定“能不能搜到”(中文依赖 IK 分词),倒排索引决定“搜得快不快”(关键词映射文档ID),二者是 ES 检索能力的核心。
-
基础操作:ES 所有操作通过 HTTP 请求完成,核心包括索引管理、文档 CRUD、各类检索(全文/精确/范围/组合),批量操作优先使用 Bulk API 提升效率。