Elasticsearch 高频面试题(高级 Java 开发版)

一、基础概念类

  1. Elasticsearch 是什么?和传统关系型数据库(MySQL)的核心区别是什么?

    • 答案:Elasticsearch 是一款分布式、RESTful 风格的全文检索与数据分析引擎,基于 Lucene 构建,支持海量数据的实时搜索、分析和存储。

    • 与 MySQL 的核心区别:

      维度 Elasticsearch MySQL
      存储模型 文档型(JSON 文档) 关系型(行、列、表)
      索引结构 倒排索引(全文检索核心) B+ 树(高效范围查询)
      核心场景 全文搜索、日志分析、数据聚合 事务性业务、结构化查询
      分布式特性 原生支持分片、副本 需依赖中间件(如 MyCat)
  2. 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(副本):分片的备份,用于故障转移和提升查询吞吐量,副本数可动态调整。
    • Type 废弃核心原因:Lucene 的底层是单一索引结构,不同 Type 的文档会存储在同一个 Lucene 索引中,字段冲突会导致字段类型混乱,影响检索效率。
  3. 什么是倒排索引?它的优缺点是什么?

    • 答案:倒排索引是全文检索的核心数据结构,与传统 "正排索引(文档→关键词)" 相反,它是关键词→文档列表 的映射。
      • 构建过程:分词器将文档内容拆分为词条(Term),记录每个词条出现在哪些文档(Doc ID)、位置(Position)、频率(TF)。
    • 优点:全文检索效率极高,能快速匹配包含某个关键词的所有文档。
    • 缺点:
      • 写入 / 更新成本高:新增或修改文档时,需要重新构建倒排索引。
      • 占用存储空间较大:需要存储词条与文档的映射关系。

二、核心原理类

  1. ES 的分片路由机制是什么?公式是什么?

    • 答案:当写入文档时,ES 会根据文档 ID 计算出该文档应该分配到哪个分片,这个过程就是分片路由。
    • 路由公式:shard = hash(routing) % number_of_primary_shards
      • routing:默认是文档的 _id,也可以自定义。
      • number_of_primary_shards:主分片数量,创建索引时固定。
    • 核心特点:路由算法决定了文档的分片归属,这也是主分片数无法动态修改的根本原因
  2. ES 的数据写入流程(Index API)是什么?refresh、flush、translog 的作用是什么?

    • 写入流程(简化版):
      1. 客户端发送写入请求到任意节点(协调节点)。
      2. 协调节点通过路由算法计算目标分片,将请求转发到该分片的主分片所在节点。
      3. 主分片写入数据到内存缓冲区 ,同时记录到translog(事务日志)
      4. 主分片将请求同步到所有副本分片,副本分片执行相同的写入操作。
      5. 所有副本分片确认写入成功后,主分片向协调节点返回成功响应,协调节点再返回给客户端。
    • 关键机制:
      • refresh :默认每隔 1 秒,将内存缓冲区的数据写入文件系统缓存 ,生成 Lucene 分段(Segment),此时数据变为可搜索状态。这就是 ES 实现近实时搜索的核心。
      • flush:默认每隔 30 分钟或 translog 达到阈值时,执行两个操作:将文件系统缓存的分段刷到磁盘;清空 translog。
      • translog :作用是保证数据可靠性,防止节点宕机时内存缓冲区的数据丢失。
  3. ES 的分词器由哪几部分组成?IK 分词器有哪两种模式?如何自定义词库?

    • 分词器组成:字符过滤器 → 分词器 → 令牌过滤器
      • 字符过滤器:预处理文本(如去除 HTML 标签)。
      • 分词器:将文本拆分为词条(如中文分词)。
      • 令牌过滤器:对词条进行加工(如转小写、停用词过滤、同义词替换)。
    • IK 分词器的两种模式:
      • ik_smart智能分词,粒度较粗(如 "中华人民共和国"→ 中华人民共和国)。
      • ik_max_word最细粒度分词,尽可能拆分(如 "中华人民共和国"→ 中华、中华人民、中华人民共和国等)。
    • 自定义词库:
      1. 在 IK 分词器的 config 目录下新建 my.dic 文件,写入自定义词汇(一行一个)。
      2. 修改 IKAnalyzer.cfg.xml,添加自定义词库配置:<entry key="ext_dict">my.dic</entry>
      3. 重启 ES 或通过 API 热更新词库。

三、性能优化类

  1. 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 倍,过多分片会导致元数据管理和分片均衡开销增大。
  2. ES 查询性能优化的核心手段有哪些?

    • 避免深分页:from + size 深分页会导致协调节点聚合大量数据,推荐使用 search_after(实时分页)或 scroll(非实时、适合批量导出)。
    • 字段类型优化:
      • 对不需要分词的字段(如 ID、手机号)设置为 keyword 类型,避免分词开销。
      • 关闭不需要的功能:如对不需要排序的字段关闭 doc_values,对不需要打分的字段使用 constant_score 查询。
    • 过滤优先:使用 filter 子句替代 must 子句,filter 结果会被缓存,提升查询效率。
    • 索引预热:对热点索引,提前执行查询将数据加载到内存,避免冷启动时的磁盘 IO 开销。
    • 硬件优化:使用 SSD 硬盘,提升内存大小(建议内存不超过 32G,避免 JVM 堆内存过大导致 GC 卡顿)。
  3. ES 中 from + size、scroll、search_after 三种分页方式的区别是什么?

    分页方式 原理 优点 缺点 适用场景
    from + size 协调节点从每个分片获取 top N 数据,再聚合排序返回 实现简单,支持随机分页 深分页时性能差,有 max_result_window 限制(默认 10000) 浅分页(页码 ≤ 100)
    scroll 生成快照,通过游标遍历分片数据 适合海量数据批量导出,性能稳定 不支持实时数据,占用服务器资源 数据导出、全量遍历
    search_after 基于上一页的最后一条数据的排序值分页 支持实时数据,无分页深度限制 不支持随机跳页,需要指定排序字段 深分页、滚动加载(如翻页列表)

四、高可用与集群管理类

  1. ES 集群脑裂问题的原因是什么?如何解决?

    • 脑裂原因:集群中主节点失联 ,其他节点重新选举主节点,导致集群出现多个主节点,数据写入出现冲突。
      • 常见诱因:网络分区(节点间网络延迟过高)、节点负载过高(GC 停顿过长)、discovery.zen.minimum_master_nodes 参数设置不合理。
    • 解决方法:
      1. 合理设置 minimum_master_nodes:该参数值为 (主节点数 / 2) + 1,确保只有超过半数主节点才能选举出主节点。
      2. 优化网络:确保节点间网络稳定,避免网络延迟过高。
      3. 控制主节点负载:主节点只负责集群管理,不存储数据和处理查询请求。
  2. ES 如何实现数据的高可用?

    • 副本机制:每个主分片对应多个副本分片,副本分片分布在不同节点,主分片故障时,副本分片会被晋升为主分片。
    • 分片均衡:ES 会自动将分片均匀分布在集群节点上,避免单节点负载过高。
    • 故障检测:通过 ping 机制检测节点存活状态,主节点定期检查从节点状态,从节点定期检查主节点状态。
    • 快照备份:定期对索引进行快照备份,存储到外部存储(如 HDFS、S3),防止数据永久丢失。
  3. 如何设计 ES 集群的冷热数据分离?

    • 核心思路:将热数据 (高频读写)存储在高性能节点(SSD + 大内存),冷数据(低频读写)存储在低成本节点(机械硬盘)。
    • 实现方案:
      1. 使用 ILM(索引生命周期管理) :定义生命周期策略(如 hot → warm → cold → delete)。
        • hot 阶段:高副本、高 refresh 频率,支持高频读写。
        • warm 阶段:降低副本数、合并分段,减少资源占用。
        • cold 阶段:将索引迁移到冷节点,设置为只读。
      2. 节点属性标记:为不同节点设置属性(如 node.attr.box_type: hot),在 ILM 策略中指定节点属性,实现索引自动迁移。

五、Java 集成与实战类

  1. Java 中操作 ES 的客户端有哪些?它们的区别是什么?

    • 主要客户端:
      1. RestHighLevelClient :官方推荐的高级 REST 客户端,支持 ES 大部分 API,同步 / 异步操作,兼容 7.x 及以上版本,是 Java 开发的首选
      2. TransportClient:基于 TCP 协议的客户端,7.x 已废弃,8.x 移除,不推荐使用。
      3. Elasticsearch Java Client:官方 8.x 推出的全新客户端,基于 Jakarta EE,支持响应式编程,是未来的主流方向。
    • 核心区别:RestHighLevelClient 基于 HTTP 协议,无需与 ES 集群版本完全一致;TransportClient 基于 TCP 协议,需要与 ES 集群版本严格一致。
  2. 使用 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();
  3. ES 中如何解决数据一致性问题?

    • 写入一致性:通过 wait_for_active_shards 参数控制,写入请求需要等待指定数量的活跃分片(主分片 + 副本分片)确认后才执行,可选值:1(只等主分片)、all(等所有分片)、自定义数量。

    • 读取一致性:通过 preference 参数控制,可选值:

      • primary:只从主分片读取,保证数据最新。
      • local:优先从本地节点读取,提升查询效率。
    • 版本控制:使用乐观锁(version + version_type),避免并发更新导致数据覆盖,例如:

      java 复制代码
      UpdateRequest request = new UpdateRequest("user_index", "1")
          .doc(XContentType.JSON, "age", 21)
          .version(1); // 版本号不匹配则更新失败

六、扩展思考类

  1. ES 在日志分析场景(如 ELK 栈)中的核心作用是什么?ELK 栈的工作流程是什么?

    • ES 作用:存储和检索海量日志数据,支持按时间、级别、关键词等维度快速查询和聚合分析。
    • ELK 工作流程:Filebeat(采集日志)→ Logstash(过滤、转换)→ Elasticsearch(存储、索引)→ Kibana(可视化展示)
  2. ES 中聚合分析(Aggregation)的原理是什么?如何优化聚合性能?

    • 原理:聚合分析分为两个阶段:
      1. 分片阶段:每个分片独立计算聚合结果。
      2. 协调节点阶段:将所有分片的聚合结果合并,得到最终结果。
    • 优化手段:
      • 使用 filter 提前过滤数据,减少聚合的数据量。
      • 对高基数字段(如用户 ID)使用 cardinality 聚合时,设置 precision_threshold 牺牲精度换性能。
      • 开启聚合缓存:对重复的聚合查询,ES 会缓存结果,提升查询效率。
相关推荐
xiaoliuliu123452 小时前
apache-tomcat-6.0.10使用步骤详解(附启动与部署教程)
java·tomcat·apache
Re_zero2 小时前
🍲 图解 JVM 内存模型:别背八股文了,直接进“Re-Zero 火锅店”干饭!
java·jvm
阿蒙Amon2 小时前
C#每日面试题-简述命名空间和程序集
java·面试·c#
烤麻辣烫2 小时前
Java开发手册规则精选
java·开发语言·学习
小宇的天下2 小时前
Virtuoso 中的tech file 详细说明
java·服务器·前端
WX-bisheyuange2 小时前
基于SpringBoot的诊疗预约平台
java·spring boot·后端·毕业设计
SimonKing2 小时前
基于Netty的WebSocket客户端
java·后端·程序员
ekkcole2 小时前
java实现对excel模版填充保存到本地后合并单元格并通过网络下载
java·开发语言·excel
Zoey的笔记本2 小时前
「软件开发缺陷管理工具」的闭环追踪设计与自动化集成架构
java·服务器·前端