一、基础概念类
-
Elasticsearch 是什么?和传统关系型数据库(MySQL)的核心区别是什么?
-
答案:Elasticsearch 是一款分布式、RESTful 风格的全文检索与数据分析引擎,基于 Lucene 构建,支持海量数据的实时搜索、分析和存储。
-
与 MySQL 的核心区别:
维度 Elasticsearch MySQL 存储模型 文档型(JSON 文档) 关系型(行、列、表) 索引结构 倒排索引(全文检索核心) B+ 树(高效范围查询) 核心场景 全文搜索、日志分析、数据聚合 事务性业务、结构化查询 分布式特性 原生支持分片、副本 需依赖中间件(如 MyCat)
-
-
ES 的核心组件(Index、Type、Document、Shard、Replica)分别是什么?Type 为什么在 7.x 被废弃?
- 核心组件:
- Index(索引) :类比 MySQL 的
Database,是一类相似文档的集合。 - Type(类型) :类比 MySQL 的
Table,7.x 后被废弃,原因是同一索引下不同 Type 的文档字段冲突会导致 Lucene 效率下降,官方推荐一个索引对应一个业务类型。 - Document(文档) :类比 MySQL 的
Row,是 ES 中最小的数据单元,以 JSON 格式存储。 - Shard(分片) :索引的水平拆分单元,解决单节点存储和查询瓶颈,分片数在索引创建时指定,后续无法修改。
- Replica(副本):分片的备份,用于故障转移和提升查询吞吐量,副本数可动态调整。
- Index(索引) :类比 MySQL 的
- Type 废弃核心原因:Lucene 的底层是单一索引结构,不同 Type 的文档会存储在同一个 Lucene 索引中,字段冲突会导致字段类型混乱,影响检索效率。
- 核心组件:
-
什么是倒排索引?它的优缺点是什么?
- 答案:倒排索引是全文检索的核心数据结构,与传统 "正排索引(文档→关键词)" 相反,它是关键词→文档列表 的映射。
- 构建过程:分词器将文档内容拆分为词条(Term),记录每个词条出现在哪些文档(Doc ID)、位置(Position)、频率(TF)。
- 优点:全文检索效率极高,能快速匹配包含某个关键词的所有文档。
- 缺点:
- 写入 / 更新成本高:新增或修改文档时,需要重新构建倒排索引。
- 占用存储空间较大:需要存储词条与文档的映射关系。
- 答案:倒排索引是全文检索的核心数据结构,与传统 "正排索引(文档→关键词)" 相反,它是关键词→文档列表 的映射。
二、核心原理类
-
ES 的分片路由机制是什么?公式是什么?
- 答案:当写入文档时,ES 会根据文档 ID 计算出该文档应该分配到哪个分片,这个过程就是分片路由。
- 路由公式:
shard = hash(routing) % number_of_primary_shardsrouting:默认是文档的_id,也可以自定义。number_of_primary_shards:主分片数量,创建索引时固定。
- 核心特点:路由算法决定了文档的分片归属,这也是主分片数无法动态修改的根本原因。
-
ES 的数据写入流程(Index API)是什么?refresh、flush、translog 的作用是什么?
- 写入流程(简化版):
- 客户端发送写入请求到任意节点(协调节点)。
- 协调节点通过路由算法计算目标分片,将请求转发到该分片的主分片所在节点。
- 主分片写入数据到内存缓冲区 ,同时记录到translog(事务日志)。
- 主分片将请求同步到所有副本分片,副本分片执行相同的写入操作。
- 所有副本分片确认写入成功后,主分片向协调节点返回成功响应,协调节点再返回给客户端。
- 关键机制:
- refresh :默认每隔 1 秒,将内存缓冲区的数据写入文件系统缓存 ,生成 Lucene 分段(Segment),此时数据变为可搜索状态。这就是 ES 实现近实时搜索的核心。
- flush:默认每隔 30 分钟或 translog 达到阈值时,执行两个操作:将文件系统缓存的分段刷到磁盘;清空 translog。
- translog :作用是保证数据可靠性,防止节点宕机时内存缓冲区的数据丢失。
- 写入流程(简化版):
-
ES 的分词器由哪几部分组成?IK 分词器有哪两种模式?如何自定义词库?
- 分词器组成:字符过滤器 → 分词器 → 令牌过滤器
- 字符过滤器:预处理文本(如去除 HTML 标签)。
- 分词器:将文本拆分为词条(如中文分词)。
- 令牌过滤器:对词条进行加工(如转小写、停用词过滤、同义词替换)。
- IK 分词器的两种模式:
ik_smart:智能分词,粒度较粗(如 "中华人民共和国"→ 中华人民共和国)。ik_max_word:最细粒度分词,尽可能拆分(如 "中华人民共和国"→ 中华、中华人民、中华人民共和国等)。
- 自定义词库:
- 在 IK 分词器的
config目录下新建my.dic文件,写入自定义词汇(一行一个)。 - 修改
IKAnalyzer.cfg.xml,添加自定义词库配置:<entry key="ext_dict">my.dic</entry>。 - 重启 ES 或通过 API 热更新词库。
- 在 IK 分词器的
- 分词器组成:字符过滤器 → 分词器 → 令牌过滤器
三、性能优化类
-
ES 写入性能优化的核心手段有哪些?
- 批量写入:使用
Bulk API替代单条写入,批量大小建议 5000 - 10000 条(根据文档大小调整)。 - 调整 refresh 间隔:将
index.refresh_interval设为 30s 或 1min(牺牲实时性换写入性能)。 - 关闭副本:写入海量数据时,先关闭副本(
index.number_of_replicas: 0),写入完成后再恢复副本,避免副本同步开销。 - 调整 translog 策略:将
index.translog.durability设为async(异步刷盘),同时调整index.translog.sync_interval控制刷盘频率。 - 合理设置分片数:分片数建议为 CPU 核心数的 1 - 3 倍,过多分片会导致元数据管理和分片均衡开销增大。
- 批量写入:使用
-
ES 查询性能优化的核心手段有哪些?
- 避免深分页:
from + size深分页会导致协调节点聚合大量数据,推荐使用search_after(实时分页)或scroll(非实时、适合批量导出)。 - 字段类型优化:
- 对不需要分词的字段(如 ID、手机号)设置为
keyword类型,避免分词开销。 - 关闭不需要的功能:如对不需要排序的字段关闭
doc_values,对不需要打分的字段使用constant_score查询。
- 对不需要分词的字段(如 ID、手机号)设置为
- 过滤优先:使用
filter子句替代must子句,filter结果会被缓存,提升查询效率。 - 索引预热:对热点索引,提前执行查询将数据加载到内存,避免冷启动时的磁盘 IO 开销。
- 硬件优化:使用 SSD 硬盘,提升内存大小(建议内存不超过 32G,避免 JVM 堆内存过大导致 GC 卡顿)。
- 避免深分页:
-
ES 中 from + size、scroll、search_after 三种分页方式的区别是什么?
分页方式 原理 优点 缺点 适用场景 from + size 协调节点从每个分片获取 top N 数据,再聚合排序返回 实现简单,支持随机分页 深分页时性能差,有 max_result_window限制(默认 10000)浅分页(页码 ≤ 100) scroll 生成快照,通过游标遍历分片数据 适合海量数据批量导出,性能稳定 不支持实时数据,占用服务器资源 数据导出、全量遍历 search_after 基于上一页的最后一条数据的排序值分页 支持实时数据,无分页深度限制 不支持随机跳页,需要指定排序字段 深分页、滚动加载(如翻页列表)
四、高可用与集群管理类
-
ES 集群脑裂问题的原因是什么?如何解决?
- 脑裂原因:集群中主节点失联 ,其他节点重新选举主节点,导致集群出现多个主节点,数据写入出现冲突。
- 常见诱因:网络分区(节点间网络延迟过高)、节点负载过高(GC 停顿过长)、
discovery.zen.minimum_master_nodes参数设置不合理。
- 常见诱因:网络分区(节点间网络延迟过高)、节点负载过高(GC 停顿过长)、
- 解决方法:
- 合理设置
minimum_master_nodes:该参数值为 (主节点数 / 2) + 1,确保只有超过半数主节点才能选举出主节点。 - 优化网络:确保节点间网络稳定,避免网络延迟过高。
- 控制主节点负载:主节点只负责集群管理,不存储数据和处理查询请求。
- 合理设置
- 脑裂原因:集群中主节点失联 ,其他节点重新选举主节点,导致集群出现多个主节点,数据写入出现冲突。
-
ES 如何实现数据的高可用?
- 副本机制:每个主分片对应多个副本分片,副本分片分布在不同节点,主分片故障时,副本分片会被晋升为主分片。
- 分片均衡:ES 会自动将分片均匀分布在集群节点上,避免单节点负载过高。
- 故障检测:通过
ping机制检测节点存活状态,主节点定期检查从节点状态,从节点定期检查主节点状态。 - 快照备份:定期对索引进行快照备份,存储到外部存储(如 HDFS、S3),防止数据永久丢失。
-
如何设计 ES 集群的冷热数据分离?
- 核心思路:将热数据 (高频读写)存储在高性能节点(SSD + 大内存),冷数据(低频读写)存储在低成本节点(机械硬盘)。
- 实现方案:
- 使用 ILM(索引生命周期管理) :定义生命周期策略(如
hot → warm → cold → delete)。hot阶段:高副本、高 refresh 频率,支持高频读写。warm阶段:降低副本数、合并分段,减少资源占用。cold阶段:将索引迁移到冷节点,设置为只读。
- 节点属性标记:为不同节点设置属性(如
node.attr.box_type: hot),在 ILM 策略中指定节点属性,实现索引自动迁移。
- 使用 ILM(索引生命周期管理) :定义生命周期策略(如
五、Java 集成与实战类
-
Java 中操作 ES 的客户端有哪些?它们的区别是什么?
- 主要客户端:
- RestHighLevelClient :官方推荐的高级 REST 客户端,支持 ES 大部分 API,同步 / 异步操作,兼容 7.x 及以上版本,是 Java 开发的首选。
- TransportClient:基于 TCP 协议的客户端,7.x 已废弃,8.x 移除,不推荐使用。
- Elasticsearch Java Client:官方 8.x 推出的全新客户端,基于 Jakarta EE,支持响应式编程,是未来的主流方向。
- 核心区别:RestHighLevelClient 基于 HTTP 协议,无需与 ES 集群版本完全一致;TransportClient 基于 TCP 协议,需要与 ES 集群版本严格一致。
- 主要客户端:
-
使用 RestHighLevelClient 实现 Bulk 批量写入的核心步骤是什么?
java// 1. 创建 RestHighLevelClient 实例 RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 2. 创建 BulkRequest BulkRequest bulkRequest = new BulkRequest(); // 3. 添加批量操作(IndexRequest/UpdateRequest/DeleteRequest) for (int i = 0; i < 1000; i++) { User user = new User("user" + i, 20 + i); IndexRequest request = new IndexRequest("user_index") .id(String.valueOf(i)) .source(JSON.toJSONString(user), XContentType.JSON); bulkRequest.add(request); } // 4. 执行批量请求 BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 5. 处理响应结果 if (bulkResponse.hasFailures()) { BulkItemResponse[] items = bulkResponse.getItems(); for (BulkItemResponse item : items) { if (item.isFailed()) { System.out.println("失败原因:" + item.getFailureMessage()); } } } // 6. 关闭客户端 client.close(); -
ES 中如何解决数据一致性问题?
-
写入一致性:通过
wait_for_active_shards参数控制,写入请求需要等待指定数量的活跃分片(主分片 + 副本分片)确认后才执行,可选值:1(只等主分片)、all(等所有分片)、自定义数量。 -
读取一致性:通过
preference参数控制,可选值:primary:只从主分片读取,保证数据最新。local:优先从本地节点读取,提升查询效率。
-
版本控制:使用乐观锁(
version+version_type),避免并发更新导致数据覆盖,例如:javaUpdateRequest request = new UpdateRequest("user_index", "1") .doc(XContentType.JSON, "age", 21) .version(1); // 版本号不匹配则更新失败
-
六、扩展思考类
-
ES 在日志分析场景(如 ELK 栈)中的核心作用是什么?ELK 栈的工作流程是什么?
- ES 作用:存储和检索海量日志数据,支持按时间、级别、关键词等维度快速查询和聚合分析。
- ELK 工作流程:
Filebeat(采集日志)→ Logstash(过滤、转换)→ Elasticsearch(存储、索引)→ Kibana(可视化展示)。
-
ES 中聚合分析(Aggregation)的原理是什么?如何优化聚合性能?
- 原理:聚合分析分为两个阶段:
- 分片阶段:每个分片独立计算聚合结果。
- 协调节点阶段:将所有分片的聚合结果合并,得到最终结果。
- 优化手段:
- 使用
filter提前过滤数据,减少聚合的数据量。 - 对高基数字段(如用户 ID)使用
cardinality聚合时,设置precision_threshold牺牲精度换性能。 - 开启聚合缓存:对重复的聚合查询,ES 会缓存结果,提升查询效率。
- 使用
- 原理:聚合分析分为两个阶段: