elasticsearch面试八股文

一、Elasticsearch 的基本概念

1、什么是Elasticsearch:

Elasticsearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎,每个字段都被索引并可被搜索,可以快速存储、搜索、分析海量的数据。

全文检索是指对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当查询时,根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

2、Elasticsearch 的基本概念:

(1)index 索引:索引类似于mysql 中的数据库,Elasticesearch 中的索引是存储数据的地方,包含了一堆有相似结构的文档数据。

(2)type 类型:类型是用来定义数据结构,可以认为是 mysql 中的一张表,type 是 index 中的一个逻辑数据分类

(3)document 文档:类似于 MySQL 中的一行,不同之处在于 ES 中的每个文档可以有不同的字段,但是对于通用字段应该具有相同的数据类型,文档是es中的最小数据单元,可以认为一个文档就是一条记录。

(4)Field 字段:Field是Elasticsearch的最小单位,一个document里面有多个field

(5)shard 分片:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。

(6)replica 副本:任何服务器随时可能故障或宕机,此时 shard 可能会丢失,通过创建 replica 副本,可以在 shard 故障时提供备用服务,保证数据不丢失,另外 replica 还可以提升搜索操作的吞吐量。

shard 分片数量在建立索引时设置,设置后不能修改,默认5个;replica 副本数量默认1个,可随时修改数量;

3、什么是倒排索引:

在搜索引擎中,每个文档都有对应的文档 ID,文档内容可以表示为一系列关键词的集合,例如,某个文档经过分词,提取了 20 个关键词,而通过倒排索引,可以记录每个关键词在文档中出现的次数和出现位置。也就是说,倒排索引是 关键词到文档 ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现了该关键词。

要注意倒排索引的两个细节:

  • 倒排索引中的所有词项对应一个或多个文档
  • 倒排索引中的词项 根据字典顺序升序排列

doc_values 的作用:

倒排索引虽然可以提高搜索性能,但也存在缺陷,比如我们需要对数据做排序或聚合等操作时,lucene 会提取所有出现在文档集合的排序字段,然后构建一个排好序的文档集合,而这个步骤是基于内存的,如果排序数据量巨大的话,容易造成内存溢出和性能缓慢。

doc_values 就是 es 在构建倒排索引的同时,会对开启 doc_values 的字段构建一个有序的 "document文档 ==> field value" 的列式存储映射,可以看作是以文档维度,实现了根据指定字段进行排序和聚合的功能,降低对内存的依赖。另外 doc_values 保存在操作系统的磁盘中,当 doc_values 大于节点的可用内存,ES可以从操作系统页缓存中加载或弹出,从而避免发生内存溢出的异常,但如果 docValues 远小于节点的可用内存,操作系统就自然将所有 doc_values 存于内存中(堆外内存),有助于快速访问。

5、text 和 keyword类型的区别:

两个类型的区别主要是分词:keyword 类型是不会分词的,直接根据字符串内容建立倒排索引,所以keyword类型的字段只能通过精确值搜索到;Text 类型在存入 Elasticsearch 的时候,会先分词,然后根据分词后的内容建立倒排索引

6、query 和 filter 的区别?

(1)query:查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;

(2)filter:查询操作仅判断是否满足查询条件,不会计算任何分值,也不会关心返回的排序问题,同时,filter 查询的结果可以被缓存,提高性能。

二、ES的写入流程:

1、ES写数据的整体流程

  • (1)客户端选择 ES 的某个 node 发送请求过去,这个 node 就是协调节点 coordinating node
  • (2)coordinating node 对 document 进行路由,将请求转发给对应的 node(有 primary shard)
  • (3)实际的 node 上的 primary shard 处理请求,然后将数据同步到 replica node
  • (4)coordinating node 等到 primary node 和所有 replica node 都执行成功之后,最后返回响应结果给客户端。

2、ES主分片写数据的详细流程:

1)主分片先将数据写入ES的 memory buffer,然后定时(默认1s)将 memory buffer 中的数据写入一个新的 segment 文件中,并进入操作系统缓存 Filesystem cache(同时清空 memory buffer),这个过程就叫做 refresh;每个 segment 文件实际上是一些倒排索引的集合, 只有经历了 refresh 操作之后,这些数据才能变成可检索的。

ES 的近实时性:数据存在 memory buffer 时是搜索不到的,只有数据被 refresh 到 Filesystem cache 之后才能被搜索到,而 refresh 是每秒一次, 所以称 es 是近实时的;可以手动调用 es 的 api 触发一次 refresh 操作,让数据马上可以被搜索到;

(2)由于 memory Buffer 和 Filesystem Cache 都是基于内存,假设服务器宕机,那么数据就会丢失,所以 ES 通过 translog 日志文件来保证数据的可靠性,在数据写入 memory buffer 的同时,将数据也写入 translog 日志文件中,当机器宕机重启时,es 会自动读取 translog 日志文件中的数据,恢复到 memory buffer 和 Filesystem cache 中去。

ES 数据丢失的问题:translog 也是先写入 Filesystem cache,然后默认每隔 5 秒刷一次到磁盘中,所以默认情况下,可能有 5 秒的数据会仅仅停留在 memory buffer 或者 translog 文件的 Filesystem cache中,而不在磁盘上,如果此时机器宕机,会丢失 5 秒钟的数据。也可以将 translog 设置成每次写操作必须是直接 fsync 到磁盘,但是性能会差很多。

(3)flush 操作:不断重复上面的步骤,translog 会变得越来越大,不过 translog 文件默认每30分钟或者 阈值超过 512M 时,就会触发 commit 操作,即 flush操作,将 memory buffer 中所有的数据写入新的 segment 文件中, 并将内存中所有的 segment 文件全部落盘,最后清空 translog 事务日志。

  • ① 将 memory buffer 中的数据 refresh 到 Filesystem Cache 中去,清空 buffer;
  • ② 创建一个新的 commit point(提交点),同时强行将 Filesystem Cache 中目前所有的数据都 fsync 到磁盘文件中;
  • ③ 删除旧的 translog 日志文件并创建一个新的 translog 日志文件,此时 commit 操作完成

三、ES的更新和删除流程:

删除和更新都是写操作,但是由于 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;所以 ES 利用 .del 文件 标记文档是否被删除,磁盘上的每个段都有一个相应的.del 文件

(1)如果是删除操作,文档其实并没有真的被删除,而是在 .del 文件中被标记为 deleted 状态。该文档依然能匹配查询,但是会在结果中被过滤掉。

(2)如果是更新操作,就是将旧的 doc 标识为 deleted 状态,然后创建一个新的 doc。

memory buffer 每 refresh 一次,就会产生一个 segment 文件 ,所以默认情况下是 1s 生成一个 segment 文件,这样下来 segment 文件会越来越多,此时会定期执行 merge。每次 merge 的时候,会将多个 segment 文件合并成一个,同时这里会将标识为 deleted 的 doc 给物理删除掉,不写入到新的 segment 中,然后将新的 segment 文件写入磁盘,这里会写一个 commit point ,标识所有新的 segment 文件,然后打开 segment 文件供搜索使用,同时删除旧的 segment 文件

四、ES的搜索流程:

搜索被执行成一个两阶段过程,即 Query Then Fetch:

1、Query阶段:

​ 客户端发送请求到 coordinate node,协调节点将搜索请求广播到所有的 primary shard 或 replica,每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。接着每个分片返回各自优先队列中 所有 docId 和 打分值 给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。

2、Fetch阶段:

​ 协调节点根据 Query阶段产生的结果,去各个节点上查询 docId 实际的 document 内容,最后由协调节点返回结果给客户端。

  • coordinate node 对 doc id 进行哈希路由,将请求转发到对应的 node,此时会使用 round-robin 随机轮询算法,在 primary shard 以及其所有 replica 中随机选择一个,让读请求负载均衡。
  • 接收请求的 node 返回 document 给 coordinate node 。
  • coordinate node 返回 document 给客户端。

Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。

五、ES在高并发下如何保证读写一致性?

1)对于更新操作:可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖

每个文档都有一个_version 版本号,这个版本号在文档被改变时加一。Elasticsearch使用这个 _version 保证所有修改都被正确排序,当一个旧版本出现在新版本之后,它会被简单的忽略。

利用_version的这一优点确保数据不会因为修改冲突而丢失,比如指定文档的version来做更改,如果那个版本号不是现在的,我们的请求就失败了。

(2)对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,副本将会在一个不同的节点上重建。

  • one:写操作只要有一个primary shard是active活跃可用的,就可以执行
  • all:写操作必须所有的primary shard和replica shard都是活跃可用的,才可以执行
  • quorum:默认值,要求ES中大部分的shard是活跃可用的,才可以执行写操作

(3)对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication 为 async 时,也可以通过设置搜索请求参数 _preference 为 primary 来查询主分片,确保文档是最新版本。

六、ES集群如何选举Master节点:

1、Elasticsearch 的分布式原理:

​ Elasticsearch 会对存储的数据进行切分,划分到不同的分片上,同时每一个分片会生成多个副本,从而保证分布式环境的高可用。ES集群中的节点是对等的,节点间会选出集群的 Master,由 Master 会负责维护集群状态信息,并同步给其他节点。

Elasticsearch 的性能会不会很低:不会,ES只有建立 index 和 type 时需要经过 Master,而数据的写入有一个简单的 Routing 规则,可以路由到集群中的任意节点,所以数据写入压力是分散在整个集群的。

2、ES集群 如何 选举 Master:

​ Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含Ping(节点之间通过这个RPC来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪些节点需要ping通)这两部分;

  • (1)确认候选主节点的最少投票通过数量(elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes)
  • (2)选举时,集群中每个节点对所有 master候选节点(node.master: true)根据 nodeId 进行字典排序,然后选出第一个节点(第0位),暂且认为它是master节点。
  • (3)如果对某个节点的投票数达到阈值,并且该节点自己也选举自己,那这个节点就是master;否则重新选举一直到满足上述条件。

补充:master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data节点可以关闭http功能。

3、Elasticsearch是如何避免脑裂现象:

(1)当集群中 master 候选节点数量不小于3个时(node.master: true),可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes),设置超过所有候选节点一半以上来解决脑裂问题,即设置为 (N/2)+1;

(2)当集群 master 候选节点 只有两个时,这种情况是不合理的,最好把另外一个node.master改成false。如果我们不改节点设置,还是套上面的(N/2)+1公式,此时discovery.zen.minimum_master_nodes应该设置为2。这就出现一个问题,两个master备选节点,只要有一个挂,就选不出master了

七、建立索引阶段性能提升方法:

  • (1)如果是大批量导入,可以设置 index.number_of_replicas: 0 关闭副本,等数据导入完成之后再开启副本
  • (2)使用批量请求并调整其大小:每次批量数据 5--15 MB 大是个不错的起始点。
  • (3)如果搜索结果不需要近实时性,可以把每个索引的 index.refresh_interval 改到30s
  • (4)增加 index.translog.flush_threshold_size 设置,从默认的 512 MB 到更大一些的值,比如 1 GB
  • (5)使用 SSD 存储介质
  • (6)段和合并:Elasticsearch 默认值是 20 MB/s。但如果用的是 SSD,可以考虑提高到 100--200 MB/s。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。

聊聊:什么是ElasticSearch?

Elasticsearch是一个基于Lucene的全文搜索引擎,也可称分布式搜索引擎,用于Java开发的,且开源,具有Http Web和无框架Json文档的分布式。

2、ElasticSearch中的集群、节点、索引、文档、类型是什么?

集群:是一个或多个服务器的集合,共同保存数据并提供所有节点的联合索引和搜索功能。集群有唯一标志,为"ElasticSearch"。

节点:节点是属于集群一部分的单体服务器,储存有数据并参与集群索引和搜索功能。如果节点设置为按名称加入集群,则该节点只能是集群的一部分。

索引:类似关系型数据库中的数据库,有一个定义多重类型的映射。索引是逻辑名称空间,可映射到一个或多个主分片,并且可以有不限个数的副本分片。

文档:文档类似关系型数据库中的数据行,不同的是处在索引中的文档可以有不同的结构或字段,但是通用字段应该具有相同的数据类型。

聊聊:列出 10 家使用 Elasticsearch 作为其应用程序的搜索引擎和数据库的公司?

参与过Elastic中文社区活动或者经常关注社区动态的人都知道,使用的公司太多了,列举如下(排名不分先后):

阿里、腾讯、字节跳动、百度、京东、美团、小米、滴滴、携程、贝壳找房、360、IBM、顺丰快递等等,几乎能想到的互联网公司都在使用Elasticsearch。

聊聊:ElasticSearch中的分片是什么?

​ 谈到分片需要谈到索引,索引是类似关系型数据库中的数据库,有一个定义多重类型的映射。索引是逻辑名称空间,可映射到一个或多个主分片,并且可以有不限个数的副本分片。因此分片是索引被分割成分布在多个节点上的元素。

聊聊:ElasticSearch特点

1、Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎

(1)查询:搜索方式随心而变。

(2)分析:可探索数据的趋势和模式。

(3)速度:速度快。

(4)可扩展性:个人和企业服务器上都可用。

(5)弹性:Elasticsearch 运行在一个分布式的环境中。

(6)灵活性:具备多个案例场景,支持所有数据类型

(7)HADOOP & SPARK : Elasticsearch + Hadoop

2、Elasticsearch是一个高度可伸缩的开源全文搜索和分析引擎。它允许您快速和接近实时地存储、搜索和分析大量数据。

这里有一些使用Elasticsearch的用例:

(1)网上商店。

(2)分析、调研日志或事务数据。

(3)实时调度用户关注信息的推送。

(4)结合Kibana (Elasticsearch/ loghide /Kibana堆栈的一部分)来构建自定义仪表板,以可视化自定义数据。此外,还可以使用Elasticsearch聚合功能对数据执行复杂的业务智能查询。

聊聊:谈谈分词与倒排索引的原理

分词:分词用于检索,英文的分词是按单词之间空格区分,中文要考虑效率和准确分词率,防止出现歧义。

倒排:根据文档内容找文档,从关键字去找文档。

倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。区别于传统的正向索引,倒排索引会再存储数据时将关键词和数据进行关联,保存到倒排表中,然后查询时,将查询内容进行分词后在倒排表中进行查询,最后匹配数

据即可。Elasticsearch 使用一种称为倒排索引的结构,ES中的倒排索引其实就是 lucene 的倒排索引 ,它适用于快速的全文搜索。正向索引(forward index),就是搜索引擎会将待搜索的文件都对应一个文件 ID,搜索时将这个ID 和搜索关键字进行对应,形成 K-V 对,然后对关键字进行统计计数。但是互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果 的要求。所以,搜索引擎会将正向索引重新构建为反向索引(inverted index,倒排索引),即把文件ID对应到关键词的映射,转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,并保存到倒排表中,查询时会将内容进行分词后在倒排表中进行查询,最后匹配数据即可。这些文件中都出现这个关键词。

聊聊:elasticsearch 的倒排索引是什么

我们传统的检索方式是通过遍历整篇文章,逐个比对找到对应的关键词位置,

而倒排索引是通过分词策略,形成词和文章的关系映射表,这种词典+映射表的方式就是倒排索引,有点类似于我们以前使用的新华字典。倒排索引可极大的提高查询效率。

聊聊:elasticsearch 索引数据多了怎么办,如何调优,部署

1.在设计的时候可以基于模板+时间滚动方式创建索引,每天递增数据,避免单个索引很大的情况出现。

2.在存储的时候,冷热数据分开存储,比如最近3天的数据作为热数据,其他的作为冷数据,冷数据的话,由于不会再写入新数据了,可以考虑定期force_merge(强制合并)和shrink(压缩)的方式进行处理,节约空间和检索效率

3.由于es支持动态扩展,所有可以多加几台机器来缓解集群压力。

聊聊:什么是近实时搜索?

在 Elasticsearch 和磁盘之间是文件系统缓存 。在内存索引缓冲区中的文档会被写入到一个新的段中。 但是这里新段会被先写入到文件系统缓存,这一步代价会比较低,稍后再被刷写到磁盘---这一步代价比较高。不过只要文件已经在缓存中,就可以像其它文件一样被打开和读取了 。在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh 。 默认情况下每个分片会每秒自动刷新一次,即刷新文件系统缓存。这就是为什么我们说 Elasticsearch 是 近实时搜索:文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。这些行为可能会对新用户造成困惑:他们索引了一个文档然后尝试搜索它,但却没有搜到。这个问题的解决办法是用 refresh API 执行一次手动刷新:/users/_refresh。

相关推荐
想ai抽20 小时前
Flink中的Lookup join和Temporal join 的语法是一样的吗?
java·大数据·flink
绝无仅有20 小时前
猿辅导面试系列:MQ消息队列解析与常见面试问题
后端·面试·github
绝无仅有20 小时前
猿辅导计算机面试文章经典总结
后端·面试·github
落雪财神意21 小时前
黄金本周想法
大数据·人工智能·金融·区块链·期股
TDengine (老段)21 小时前
TDengine 数学函数 PI 用户手册
大数据·数据库·时序数据库·iot·tdengine·涛思数据
lang2015092821 小时前
Spring Boot Actuator应用信息Application Information全解析
spring boot·后端·elasticsearch
三口吃掉你1 天前
Docker安装Elasticsearch、kibana、IK分词器
elasticsearch·docker·kibana·ik分词器
怪兽20141 天前
Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么?
android·面试
ikoala1 天前
Node.js 25 正式发布:性能飙升、安全升级、全面向 Web 靠拢!
前端·面试·node.js
木易 士心1 天前
Android 开发核心知识体系与面试指南精简版
android·面试·职场和发展