1. Elasticsearch 是什么?有哪些应用场景? Elasticsearch 整体原理流程?
Elasticsearch 是一个为海量数据提供近实时搜索和分析能力的分布式搜索引擎,广泛应用于全文检索、日志分析和大数据处理场景中。
Elasticsearch 整体原理流程:
1.建索引(Index)与定义 Mapping:建索引,相当于创建一个逻辑的数据容器,用于存放文档。Mapping,定义索引中字段的数据类型、分词器、是否索引等属性,类似数据库的 schema。通过 mapping,ES 知道如何解析和存储每个字段的数据,如何分词建立倒排索引。
-
插入文档(Document):用户提交 JSON 格式的文档,写入到指定的索引中。ES 根据 mapping 解析字段,对需要分词的字段进行分词处理(Tokenizer + Token Filters),生成词项(tokens)。对每个词项建立倒排索引,记录词项在哪些文档中出现,以及出现频率、位置等信息。文档数据会被存储在主分片(Primary Shard)及其副本分片(Replica Shard)中,保证数据高可用。写操作异步刷新到磁盘,提高写入性能。
-
查询流程:查询请求发到集群的某个节点(协调节点)。协调节点根据索引的分片信息,将查询请求广播到所有相关的主分片和副本分片。对查询语句进行解析,针对查询字段使用对应的分词器分词(如 match 查询)。在倒排索引中查找词项,快速定位匹配文档 ID。计算文档相关度得分(基于 TF-IDF 或 BM25 算法等),排序。各分片返回结果给协调节点。协调节点合并各分片结果,进行排序分页,返回最终结果给客户端。
2. 倒排索引是什么?为什么适合全文检索?
在理解倒排索引之前,先看一下正排索引。正排索引是从"文档到词"的映射,也就是说:每个文档记录了它包含的所有词。而倒排索引则是相反的:它是从"词到文档"的映射,即:每个词会记录它出现在哪些文档中。
当我们搜索一个词时,只需通过倒排索引快速定位所有包含该词的文档,而不需要对所有文档内容进行全文扫描,大大提升了搜索性能。此外,倒排索引还可以记录每个词在各个文档中出现的频率、位置等信息,用于相关性打分(如 BM25 算法),从而实现搜索结果的排序和精准匹配。因此,倒排索引非常适合实现高性能的全文搜索,是搜索引擎(如 Elasticsearch)核心的数据结构之一。
3. ES 中的文档(Document)、索引(Index)、类型(Type)是什么?
在 Elasticsearch 中,最基本的数据单位是 Document(文档),它就像数据库中的一行数据,JSON 格式存储。
文档是存在哪个 Index(索引) 里的,索引可以类比为数据库或表,是文档的逻辑集合。
早期 ES 中还支持 Type(类型),一个 Index 下可以有多个 Type,相当于一个数据库里有多个表。但因为底层结构冲突,从 6.x 开始被逐步废弃,7.x 开始每个索引只能有一个 Type,8.x 完全移除。
所以现在实际开发中,一个索引通常只存一种类型的文档,不再使用 Type。
比如我们项目中有商品搜索功能,就会创建一个 product_index
,每条商品数据就是一个文档,包含商品名、描述、价格等字段,然后通过这个索引来实现搜索和过滤。
4. 什么是 Mapping?和数据库中的 schema 有什么区别?
在 Elasticsearch 中,索引(Index)通过 Mapping 来定义文档结构,包括字段名、字段类型、是否索引、是否分词等规则,相当于定义表的结构。
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "standard" },
"price": { "type": "float" },
"in_stock": { "type": "boolean" },
"created_at": { "type": "date" }
}
}
}
文档(Document)是索引中的一条具体数据记录,以 JSON 格式存储,结构要符合 Mapping 的定义。
POST /products/_doc/1
{
"name": "Apple iPhone 14",
"price": 799.99,
"in_stock": true,
"created_at": "2024-06-01T10:00:00Z"
}
所以可以理解为:Mapping 决定了索引中能存什么样的数据结构,文档就是实际存进去的数据。
在 Elasticsearch 中,Mapping 类似于数据库中的 Schema,它定义了每个文档字段的数据类型、是否分词、是否索引、分词器、是否支持聚合等规则。
不同于数据库,ES 的 Mapping 更加灵活,比如可以支持嵌套结构、数组、动态字段,还能定义全文检索相关的分词方式,是搜索性能调优的重要部分。
5. ES 中 match
和 term
查询的区别?
在 Elasticsearch 中,match 查询是 全文检索 类型的查询,它会对查询条件先进行分词,然后再去倒排索引中查找对应的文档,常用于搜索 text 类型字段,比如商品描述、文章内容等。
term 查询则是 精确匹配 查询,它不会进行分词,直接使用给定的值去匹配字段,常用于 keyword、数值、布尔值等字段的过滤或精确判断。
所以两者的核心区别就是:match 会分词,适合模糊查询;term 不分词,适合精确查询。
6. ES 是怎么进行分词的?常用的分词器有哪些?
Elasticsearch 使用 分词器(Analyzer) 来对文本字段进行处理,分词器会将一段文本拆分为一个个词项(term)并进行标准化,例如大小写转换、去除符号、删除停用词等。
分词器一般包含三个组件:
1.字符过滤器(Char Filters):预处理文本,如去除 HTML 标签。
2.分词器(Tokenizer):将文本切分成词(最核心部分)。
3.词项过滤器(Token Filters):对分词结果进行加工,比如大小写统一、去除停用词、同义词处理等。
常用分词器:
1.standard:默认分词器,按空格、标点分词,同时做大小写标准化
输入: I'm learning Elasticsearch.
输出:i, m, learning, elasticsearch
2.simple:以非字母字符为分隔符,只保留小写英文
输入: Hello, World!
输出: hello, world
3.whitespace:仅以空格分词,不做其他处理
输入: Hello, World!
输出: hello, world
4.keyword:不分词,把整个输入当成一个词项
输入: 中华人民共和国
输出: 中华人民共和国
5.ik_max_word:中文分词器,细粒度,尽可能多的切词
输入: 中国互联网公司
输出: 中国, 互联网, 公司, 中国互联网, 互联网公司
6.ik_smart:中文分词器,粗粒度,分得较少但准确
输入: 中国互联网公司
输出: 中国互联网, 公司
7. 什么是主分片(Primary Shard)和副本分片(Replica Shard)?
在 Elasticsearch 中,索引的数据是通过主分片和副本分片进行分布式存储的。
主分片(Primary Shard)负责实际写入和保存原始数据;副本分片(Replica Shard)是主分片的冗余副本,用于容灾备份和查询负载均衡。
通常每个主分片至少配置一个副本,从而保证当某个节点宕机时数据不会丢失,并且查询时可以由多个分片并行处理提升性能。
主分片负责写入,副本分片负责高可用和查询负载分担;主分片挂了,副本可以自动转为主分片,保障数据可靠性。
8. ES 是如何保证高可用的?节点挂掉会怎样?
Elasticsearch 通过主/副分片机制、Master 选举机制以及自动分片迁移能力实现高可用。
当某个节点宕机时,集群会自动将其主分片由副本接管,并在其他节点上重新构建副本,从而实现无缝切换,保证查询和写入的连续性。同时,Master 节点也有选举机制,避免单点故障,整个集群能自动感知变化并自我修复。
节点挂掉会发生什么?
Elasticsearch 会立刻识别失联节点(默认 30 秒内)。
该节点上的主分片如果有副本,副本会自动被提升为主分片。
副本不足的部分,会被自动重新分配到其他节点上重建副本。
查询和写入请求会自动路由到新的主分片或其副本,不会影响业务使用。
如果主节点宕机,会触发主节点重新选举机制,集群会暂时处于 yellow 状态,自动恢复后变回 green。
9. 怎么保证 ES 和数据库之间的数据一致性?
保证 ES 和数据库之间数据一致,关键在于解决异步同步导致的最终一致性问题:
- 幂等写入
ES 写入接口要设计幂等,避免重复写入产生脏数据。
常用 document id 由业务唯一主键生成。
- 异步消息可靠传递
使用消息队列保障消息不丢失(持久化、确认机制)。
设计消息重试机制,处理写 ES 失败。
- 事务保证与补偿机制
有条件的场景使用分布式事务(如基于消息中间件的事务模式)。
定时全量校验比对,发现不一致后自动修复。
- 顺序消费
保证消息顺序消费,避免旧数据覆盖新数据。
- 监控和告警
监控同步延迟和失败率,及时人工干预。
10. 实际项目中一般数据是怎么同步到 ES 的?
- 应用程序主动写入(同步写入)
在业务系统(如数据库)写操作后,直接调用 Elasticsearch API 进行索引写入。
- 异步同步(消息队列/日志异步消费)
业务系统将数据变更事件发送到消息队列(Kafka、RabbitMQ 等)。专门的同步服务监听消息队列,异步写入 Elasticsearch。
- 定时全量同步 + 增量同步
定时全量同步是指周期性(比如每天凌晨)将数据库中的所有数据一次性批量导入 Elasticsearch。目的是初始化数据或修复数据不一致问题。
增量同步是指只同步自上次同步后数据库中新增加或变更的数据。可以通过基于业务表的时间戳字段(如 update_time
)进行差量查询;使用数据库变更日志(binlog)捕获变更事件;监听消息队列中实时数据变更事件来实现增量同步。