【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?

沙海 2021年3月11日06:49:30杂谈 Java评论58字数 5024阅读16分44秒阅读模式
摘要

速读摘要

速读摘要文章源自JAVA秀-https://www.javaxiu.com/3665.html

客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)。协调节点将搜索请求转发到所有的shard对应的primary shard或replica shard,都可以。一旦此时机器宕机,再次重启的时候,es会自动读取translog日志文件中的数据,恢复到内存buffer和os cache中去。或者translog文件的os cache中,如果此时机器挂了,会丢失5秒钟的数据。文章源自JAVA秀-https://www.javaxiu.com/3665.html

原文约 3299 | 图片 5 | 建议阅读 7 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/3665.html

【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?

戳一戳→ 程序员的成长之路 文章源自JAVA秀-https://www.javaxiu.com/3665.html

【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

程序员的成长之路文章源自JAVA秀-https://www.javaxiu.com/3665.html

互联网/程序员/技术/资料共享 文章源自JAVA秀-https://www.javaxiu.com/3665.html

关注文章源自JAVA秀-https://www.javaxiu.com/3665.html

阅读本文大概需要 7 分钟。文章源自JAVA秀-https://www.javaxiu.com/3665.html

来自https://doocs.gitee.io/#/文章源自JAVA秀-https://www.javaxiu.com/3665.html

面试题

ES 写入数据的工作原理是什么啊?ES 查询数据的工作原理是什么啊?底层的 Lucene 介绍一下呗?倒排索引了解吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

面试官心理分析

问这个,其实面试官就是要看看你了解不了解 es 的一些基本原理,因为用 es 无非就是写入数据,搜索数据。你要是不明白你发起一个写入和搜索请求的时候,es 在干什么,那你真的是......文章源自JAVA秀-https://www.javaxiu.com/3665.html

对 es 基本就是个黑盒,你还能干啥?你唯一能干的就是用 es 的 api 读写数据了。要是出点什么问题,你啥都不知道,那还能指望你什么呢?文章源自JAVA秀-https://www.javaxiu.com/3665.html

面试题剖析

es 写数据过程

  • 客户端选择一个 node 发送请求过去,这个 node 就是 coordinating node (协调节点)。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • coordinating node 对 document 进行路由,将请求转发给对应的 node(有 primary shard)。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 实际的 node 上的 primary shard 处理请求,然后将数据同步到 replica node 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • coordinating node 如果发现 primary node 和所有 replica node 都搞定之后,就返回响应结果给客户端。文章源自JAVA秀-https://www.javaxiu.com/3665.html

【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

es-write文章源自JAVA秀-https://www.javaxiu.com/3665.html

es 读数据过程

可以通过 doc id 来查询,会根据 doc id 进行 hash,判断出来当时把 doc id 分配到了哪个 shard 上面去,从那个 shard 去查询。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 客户端发送请求到任意一个 node,成为 coordinate node 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • coordinate node 对 doc id 进行哈希路由,将请求转发到对应的 node,此时会使用 round-robin 随机轮询算法,在 primary shard 以及其所有 replica 中随机选择一个,让读请求负载均衡。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 接收请求的 node 返回 document 给 coordinate node 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • coordinate node 返回 document 给客户端。文章源自JAVA秀-https://www.javaxiu.com/3665.html

es 搜索数据过程

es 最强大的是做全文检索,就是比如你有三条数据:文章源自JAVA秀-https://www.javaxiu.com/3665.html

java真好玩儿啊java好难学啊j2ee特别牛Copy to clipboardErrorCopied

你根据 java 关键词来搜索,将包含 java 的 document 给搜索出来。es 就会给你返回:java真好玩儿啊,java好难学啊。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 客户端发送请求到一个 coordinate node 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 协调节点将搜索请求转发到所有的 shard 对应的 primary shard 或 replica shard ,都可以。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • query phase:每个 shard 将自己的搜索结果(其实就是一些 doc id )返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • fetch phase:接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。文章源自JAVA秀-https://www.javaxiu.com/3665.html

写请求是写入 primary shard,然后同步给所有的 replica shard;读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。文章源自JAVA秀-https://www.javaxiu.com/3665.html

写数据底层原理

【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

es-write-detail文章源自JAVA秀-https://www.javaxiu.com/3665.html

先写入内存 buffer,在 buffer 里的时候数据是搜索不到的;同时将数据写入 translog 日志文件。文章源自JAVA秀-https://www.javaxiu.com/3665.html

如果 buffer 快满了,或者到一定时间,就会将内存 buffer 数据 refresh 到一个新的 segment file 中,但是此时数据不是直接进入 segment file 磁盘文件,而是先进入 os cache 。这个过程就是 refresh 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

每隔 1 秒钟,es 将 buffer 中的数据写入一个新的 segment file ,每秒钟会产生一个新的磁盘文件 segment file ,这个 segment file 中就存储最近 1 秒内 buffer 中写入的数据。文章源自JAVA秀-https://www.javaxiu.com/3665.html

但是如果 buffer 里面此时没有数据,那当然不会执行 refresh 操作,如果 buffer 里面有数据,默认 1 秒钟执行一次 refresh 操作,刷入一个新的 segment file 中。文章源自JAVA秀-https://www.javaxiu.com/3665.html

操作系统里面,磁盘文件其实都有一个东西,叫做 os cache ,即操作系统缓存,就是说数据写入磁盘文件之前,会先进入 os cache ,先进入操作系统级别的一个内存缓存中去。只要 buffer 中的数据被 refresh 操作刷入 os cache 中,这个数据就可以被搜索到了。文章源自JAVA秀-https://www.javaxiu.com/3665.html

为什么叫 es 是准实时的?NRT ,全称 near real-time 。默认是每隔 1 秒 refresh 一次的,所以 es 是准实时的,因为写入的数据 1 秒之后才能被看到。可以通过 es 的 restful api 或者 java api ,手动执行一次 refresh 操作,就是手动将 buffer 中的数据刷入 os cache 中,让数据立马就可以被搜索到。只要数据被输入 os cache 中,buffer 就会被清空了,因为不需要保留 buffer 了,数据在 translog 里面已经持久化到磁盘去一份了。文章源自JAVA秀-https://www.javaxiu.com/3665.html

重复上面的步骤,新的数据不断进入 buffer 和 translog,不断将 buffer 数据写入一个又一个新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。随着这个过程推进,translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发 commit 操作。文章源自JAVA秀-https://www.javaxiu.com/3665.html

commit 操作发生第一步,就是将 buffer 中现有数据 refresh 到 os cache 中去,清空 buffer。然后,将一个 commit point 写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file ,同时强行将 os cache 中目前所有的数据都 fsync 到磁盘文件中去。最后清空 现有 translog 日志文件,重启一个 translog,此时 commit 操作完成。文章源自JAVA秀-https://www.javaxiu.com/3665.html

这个 commit 操作叫做 flush 。默认 30 分钟自动执行一次 flush ,但如果 translog 过大,也会触发 flush 。flush 操作就对应着 commit 的全过程,我们可以通过 es api,手动执行 flush 操作,手动将 os cache 中的数据 fsync 强刷到磁盘上去。文章源自JAVA秀-https://www.javaxiu.com/3665.html

translog 日志文件的作用是什么?你执行 commit 操作之前,数据要么是停留在 buffer 中,要么是停留在 os cache 中,无论是 buffer 还是 os cache 都是内存,一旦这台机器死了,内存中的数据就全丢了。所以需要将数据对应的操作写入一个专门的日志文件 translog 中,一旦此时机器宕机,再次重启的时候,es 会自动读取 translog 日志文件中的数据,恢复到内存 buffer 和 os cache 中去。文章源自JAVA秀-https://www.javaxiu.com/3665.html

translog 其实也是先写入 os cache 的,默认每隔 5 秒刷一次到磁盘中去,所以默认情况下,可能有 5 秒的数据会仅仅停留在 buffer 或者 translog 文件的 os cache 中,如果此时机器挂了,会丢失 5 秒钟的数据。但是这样性能比较好,最多丢 5 秒的数据。也可以将 translog 设置成每次写操作必须是直接 fsync 到磁盘,但是性能会差很多。文章源自JAVA秀-https://www.javaxiu.com/3665.html

实际上你在这里,如果面试官没有问你 es 丢数据的问题,你可以在这里给面试官炫一把,你说,其实 es 第一是准实时的,数据写入 1 秒后可以搜索到;可能会丢失数据的。有 5 秒的数据,停留在 buffer、translog os cache、segment file os cache 中,而不在磁盘上,此时如果宕机,会导致 5 秒的数据丢失文章源自JAVA秀-https://www.javaxiu.com/3665.html

总结一下,数据先写入内存 buffer,然后每隔 1s,将数据 refresh 到 os cache,到了 os cache 数据就能被搜索到(所以我们才说 es 从写入到能被搜索到,中间有 1s 的延迟)。每隔 5s,将数据写入 translog 文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据丢失),translog 大到一定程度,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。文章源自JAVA秀-https://www.javaxiu.com/3665.html

数据写入 segment file 之后,同时就建立好了倒排索引。文章源自JAVA秀-https://www.javaxiu.com/3665.html

删除/更新数据底层原理

如果是删除操作,commit 的时候会生成一个 .del 文件,里面将某个 doc 标识为 deleted 状态,那么搜索的时候根据 .del 文件就知道这个 doc 是否被删除了。文章源自JAVA秀-https://www.javaxiu.com/3665.html

如果是更新操作,就是将原来的 doc 标识为 deleted 状态,然后新写入一条数据。文章源自JAVA秀-https://www.javaxiu.com/3665.html

buffer 每 refresh 一次,就会产生一个 segment file ,所以默认情况下是 1 秒钟一个 segment file ,这样下来 segment file 会越来越多,此时会定期执行 merge。每次 merge 的时候,会将多个 segment file 合并成一个,同时这里会将标识为 deleted 的 doc 给物理删除掉,然后将新的 segment file 写入磁盘,这里会写一个 commit point ,标识所有新的 segment file ,然后打开 segment file 供搜索使用,同时删除旧的 segment file 。文章源自JAVA秀-https://www.javaxiu.com/3665.html

底层 lucene

简单来说,lucene 就是一个 jar 包,里面包含了封装好的各种建立倒排索引的算法代码。我们用 Java 开发的时候,引入 lucene jar,然后基于 lucene 的 api 去开发就可以了。文章源自JAVA秀-https://www.javaxiu.com/3665.html

通过 lucene,我们可以将已有的数据建立索引,lucene 会在本地磁盘上面,给我们组织索引的数据结构。文章源自JAVA秀-https://www.javaxiu.com/3665.html

倒排索引

在搜索引擎中,每个文档都有一个对应的文档 ID,文档内容被表示为一系列关键词的集合。例如,文档 1 经过分词,提取了 20 个关键词,每个关键词都会记录它在文档中出现的次数和出现位置。文章源自JAVA秀-https://www.javaxiu.com/3665.html

那么,倒排索引就是关键词到文档 ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现了关键词。文章源自JAVA秀-https://www.javaxiu.com/3665.html

举个栗子。文章源自JAVA秀-https://www.javaxiu.com/3665.html

有以下文档:文章源自JAVA秀-https://www.javaxiu.com/3665.html

DocIdDoc
1谷歌地图之父跳槽 Facebook
2谷歌地图之父加盟 Facebook
3谷歌地图创始人拉斯离开谷歌加盟 Facebook
4谷歌地图之父跳槽 Facebook 与 Wave 项目取消有关
5谷歌地图之父拉斯加盟社交网站 Facebook

对文档进行分词之后,得到以下倒排索引文章源自JAVA秀-https://www.javaxiu.com/3665.html

WordIdWordDocIds
1谷歌1, 2, 3, 4, 5
2地图1, 2, 3, 4, 5
3之父1, 2, 4, 5
4跳槽1, 4
5Facebook1, 2, 3, 4, 5
6加盟2, 3, 5
7创始人3
8拉斯3, 5
9离开3
104
......

另外,实用的倒排索引还可以记录更多的信息,比如文档频率信息,表示在文档集合中有多少个文档包含某个单词。文章源自JAVA秀-https://www.javaxiu.com/3665.html

那么,有了倒排索引,搜索引擎可以很方便地响应用户的查询。比如用户输入查询 Facebook ,搜索系统查找倒排索引,从中读出包含这个单词的文档,这些文档就是提供给用户的搜索结果。文章源自JAVA秀-https://www.javaxiu.com/3665.html

要注意倒排索引的两个重要细节:文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 倒排索引中的所有词项对应一个或多个文档;文章源自JAVA秀-https://www.javaxiu.com/3665.html

  • 倒排索引中的词项根据字典顺序升序排列文章源自JAVA秀-https://www.javaxiu.com/3665.html

上面只是一个简单的例子,并没有严格按照字典顺序升序排列。文章源自JAVA秀-https://www.javaxiu.com/3665.html

<END>文章源自JAVA秀-https://www.javaxiu.com/3665.html

推荐阅读:文章源自JAVA秀-https://www.javaxiu.com/3665.html

【153期】面试官:谈谈常用的Arraylist和Linkedlist的区别文章源自JAVA秀-https://www.javaxiu.com/3665.html

【152期】面试官:你能说出MySQL主从复制的几种复制方式吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

【151期】谈谈 ZooKeeper 的定位:能解决什么问题?不能解决什么问题?文章源自JAVA秀-https://www.javaxiu.com/3665.html

5T技术资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,单片机,树莓派,等等。在公众号内回复「2048」,即可免费获取!!文章源自JAVA秀-https://www.javaxiu.com/3665.html

【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

微信扫描二维码,关注我的公众号文章源自JAVA秀-https://www.javaxiu.com/3665.html

朕已阅 【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?文章源自JAVA秀-https://www.javaxiu.com/3665.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定