互联网Java工程师面试题·Elasticsearch 篇·第二弹

12、详细描述一下 Elasticsearch 索引文档的过程。

协调节点默认使用文档 ID 参与计算(也支持通过 routing ),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
1 、当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认是每隔 1 秒)写入到 Filesystem Cache ,这个从 Momery Buffer 到 Filesystem Cache 的过程就叫做 refresh
2 、当然在某些情况下,存在 Momery Buffer Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush
3 、在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog
4 flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512M )时;

补充:关于 Lucene Segement
1 Lucene 索引是由多个段组成,段本身是一个功能齐全的倒排索引。
2 、段是不可变的,允许 Lucene 将新的文档增量地添加到索引中,而不用从头重建索引。
3 、对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗CPU 的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。
4 、为了解决 这个 问题 , Elasticsearch 会合并小段到一个较大的段,提交新的合并段到磁盘,并删除那些旧的小段。

13、详细描述一下 Elasticsearch 更新和删除文档的过程。

1 、删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;
2 、磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真的被删除,而是在.del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入新段。
3 、在新的文档被创建时, Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。

14、详细描述一下 Elasticsearch 搜索的过程。

1 、搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch
2 、在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。
PS :在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的。
3 、每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
4 、接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
5 、补充: Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term Document frequency ,这个评分更准确,但是性能会变差。*


15、在 Elasticsearch 中,是怎么根据一个词找到对应的倒排索引的?

SEE
Lucene学习总结之三:Lucene的索引文件格式(1) - 刘超觉先 - 博客园 (cnblogs.com)
Lucene学习总结之三:Lucene的索引文件格式(2) - 刘超觉先 - 博客园 (cnblogs.com)

16Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?

1 64 GB 内存的机器是非常理想的, 但是 32 GB 16 GB 机器也是很常见的。少于 8 GB 会适得其反。
2 、如果你要在更快的 CPUs 和更多的核心之间选择,选择更多的核心更好。多个内核提供的额外并发远胜过稍微快一点点的时钟频率。
3 、如果你负担得起 SSD ,它将远远超出任何旋转介质。 基于 SSD 的节点,查询和索引性能都有提升。如果你负担得起,SSD 是一个好的选择。
4 、即使数据中心们近在咫尺,也要避免集群跨越多个数据中心。绝对要避免集群跨越大的地理距离。
5 、请确保运行你应用程序的 JVM 和服务器的 JVM 是完全一样的。 在Elasticsearch 的几个地方,使用 Java 的本地序列化。
6 、通过设置 gateway.recover_after_nodes gateway.expected_nodes 、 gateway.recover_after_time 可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟。
7 Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。最好使用单播代替组播。
8 、不要随意修改垃圾回收器( CMS )和各个线程池的大小。
9 、把你的内存的(少于)一半给 Lucene (但不要超过 32 GB !),通过ES_HEAP_SIZE 环境变量设置。
10 、内存交换到磁盘对服务器性能来说是致命的。如果内存交换到磁盘上,一个100 微秒的操作可能变成 10 毫秒。 再想想那么多 10 微秒的操作时延累加起来。 不难看出 swapping 对于性能是多么可怕。
11 Lucene 使用了大量 的文件。同时, Elasticsearch 在节点和 HTTP 客户端之间进行通信也使用了大量的套接字。 所有这一切都需要足够的文件描述符。你应该增加你的文件描述符,设置一个很大的值,如 64,000
补充:索引阶段性能提升方法
1 、使用批量请求并调整其大小:每次批量数据 5–15 MB 大是个不错的起始点。
2 、存储:使用 SSD
3 、段和合并: Elasticsearch 默认值是 20 MB/s ,对机械磁盘应该是个不错的设置。如果你用的是 SSD ,可以考虑提高到 100–200 MB/s 。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。另外还可以增加 index.translog.flush_threshold_size 设置,从默认的 512 MB 到更大一些的值,比如 1 GB,这可以在一次清空触发的时候在事务日志里积累出更大的段。
4 、如果你的搜索结果不需要近实时的准确度,考虑把每个索引的
index.refresh_interval 改到 30s
5 、如果你在做大批量导入,考虑通过设置 index.number_of_replicas: 0 关闭副本。

17、对于 GC 方面,在使用 Elasticsearch 时要注意什么?

1 SEE https://elasticsearch.cn/article/32
2 、倒排词典的索引需要常驻内存,无法 GC ,需要监控 data node segment memory 增长趋势。
3 、各类缓存, field cache, filter cache, indexing cache, bulk queue 等等,要设置合理的大小,并且要应该根据最坏的情况来看 heap 是否够用,也就是各类缓存全部占满的时候,还有 heap 空间可以分配给其他任务吗?避免采用 clear cache等“ 自欺欺人 的方式来释放内存。
4 、避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api 来实现。
5 cluster stats 驻留内存并无法水平扩展,超大规模集群可以考虑分拆成多个集群通过 tribe node 连接。
6 、想知道 heap 够不够,必须结合实际应用场景,并对集群的 heap 使用情况做
持续的监控。

18、Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?

        Elasticsearch 提供的首个近似聚合是 cardinality 度量。它提供一个字段的基数,即该字段的 distinct 或者 unique 值的数目。它是基于 HLL 算法的。 HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关

19、在并发情况下,Elasticsearch 如果保证读写一致?

1 、可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
2 、另外对于写操作,一致性级别支持 quorum/one/all ,默认为 quorum ,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。
3 、对于读操作,可以设置 replication sync( 默认 ) ,这使得操作在主分片和副本分片都完成后才会返回;如果设置 replication async 时,也可以通过设置搜索请求参数_preference primary 来查询主分片,确保文档是最新版本。

20、如何监控 Elasticsearch 集群状态?

        Marvel 让你可以很简单的通过 Kibana 监控 Elasticsearch 。你可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标。

21、介绍下你们电商搜索的整体技术架构。


22、介绍一下你们的个性化搜索方案?

SEE 基于 word2vec Elasticsearch 实现个性化搜索


23、是否了解字典树?

常用字典数据结构如下所示:

Trie 的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有 3 个基本性质:
1 、根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2 、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3 、每个节点的所有子节点包含的字符都不相同。

1 、可以看到, trie 树每一层的节点数是 26^i 级别的。所以为了节省空间,我们还可以用动态链表,或者用数组来模拟动态。而空间的花费,不会超过单词数× 单词长度。
2 、实现:对每个结点开一个字母集大小的数组,每个结点挂一个链表,使用左儿子右兄弟表示法记录这棵树;
3 、对于中文的字典树,每个节点的子节点用一个哈希表存储,这样就不用浪费太大的空间,而且查询速度上可以保留哈希的复杂度 O(1)

24、拼写纠错是如何实现的?

1 、拼写纠错是基于编辑距离来实现;编辑距离是一种标准的方法,它用来表示经过插入、删除和替换操作从一个字符串转换到另外一个字符串的最小操作步数;
2 、编辑距离的计算过程:比如要计算 batyu beauty 的编辑距离,先创建一个7×8 的表( batyu 长度为 5 coffee 长度为 6 ,各加 2 ),接着,在如下位置填入黑色数字。其他格的计算过程是取以下三个值的最小值:
如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字+1。(对于 3,3 来说为 0
左方数字 +1 (对于 3,3 格来说为 2
上方数字 +1 (对于 3,3 格来说为 2
最终取右下角的值即为编辑距离的值 3

对于拼写纠错,我们考虑构造一个度量空间( Metric Space ),该空间内任何关系满足以下三条基本条件:
d(x,y) = 0 -- 假如 x y 的距离为 0 ,则 x=y
d(x,y) = d(y,x) -- x y 的距离等同于 y x 的距离
d(x,y) + d(y,z) >= d(x,z) -- 三角不等式
1 、根据三角不等式,则满足与 query 距离在 n 范围内的另一个字符转 B ,其与 A 的距离最大为 d+n ,最小为 d-n
2 BK 树的构造就过程如下:每个节点有任意个子节点,每条边有个值表示编辑距离。所有子节点到父节点的边上标注 n 表示编辑距离恰好为 n 。比如,我们有棵树父节点是”book”和两个子节点 ”cake” ”books” ”book” ”books” 的边标号 1 ”book” ”cake” 的边上标号 4 。从字典里构造好树后,无论何 时你想插入新单词时,计算该单词与根节点的编辑距离,并且查找数值为 d(neweord, root)的边。递归得与各子节点进行比较,直到没有子节点,你就可 以创建新的子节点并将新单词保存在那。比如,插入”boo” 到刚才上述例子的树中,我们先检查根节点,查找 d(“book”, “boo”) = 1 的边,然后检查标号为 1 的边的子节点,得到单词 ”books” 。我们再计算距离 d(“books”, “boo”)=2 ,则将新单词插在”books” 之后,边标号为 2
3 、查询相似词如下:计算单词与根节点的编辑距离 d ,然后递归查找每个子节点标号为 d-n d+n (包含)的边。假如被检查的节点与搜索单词的距离 d 小于 n ,则返回该节点并继续查询。比如输入 cape 且最大容忍距离为 1 ,则先计算和根的编辑距离 d(“book”, “cape”)=4 ,然后接着找和根节点之间编辑距离为 3 到5 的,这个就找到了 cake 这个节点,计算 d(“cake”, “cape”)=1 ,满足条件所以返回 cake ,然后再找和 cake 节点编辑距离是 0 2 的,分别找到 cape 和cart 节点,这样就得到 cape 这个满足条件的结果。


要想了解更多:

千题千解·Java面试宝典_时光の尘的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95552.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题 518零钱兑换2(完全背包)

题目 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整…

API基础————包

什么是包,package实际上就是一个文件夹,便于程序员更好的管理维护自己的代码。它可以使得一个项目结构更加清晰明了。 Java也有20年历史了,这么多年有这么多程序员写了无数行代码,其中有大量重复的,为了更加便捷省时地…

Flv.js编译使用

Flv.js (https://github.com/bilibili/flv.js)是 HTML5 Flash 视频(FLV)播放器,纯原生 JavaScript 开发,没有用到 Flash。由 bilibili 网站开源。本文讲述其编译使用。 Flv.js目前最新版本是v1.6.2。在htt…

基于混合蛙跳优化的BP神经网络(分类应用) - 附代码

基于混合蛙跳优化的BP神经网络(分类应用) - 附代码 文章目录 基于混合蛙跳优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.混合蛙跳优化BP神经网络3.1 BP神经网络参数设置3.2 混合蛙跳算法应用 4.测试结果…

gitgitHub

在git中复制CtrlInsert、粘贴CtrlShif 一、用户名和邮箱的配置 查看用户名 :git config user.name 查看密码: git config user.password 查看邮箱:git config user.email 查看配置信息: $ git config --list 修改用户名 git co…

Java笔记七(封装,继承与多态)

封装 该露的露,该藏的藏 程序设计追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用 封装(数据的隐藏) 通常,…

【Pandas】Apply自定义行数

文章目录 1. Series的apply方法2. DataFrame的apply方法2.1 针对列使用apply2.2 针对行使用apply Pandas提供了很多数据处理的API,但当提供的API不能满足需求的时候,需要自己编写数据处理函数, 这个时候可以使用apply函数apply函数可以接收一个自定义函数, 可以将DataFrame的行…

Linux shell编程学习笔记8:使用字符串

一、前言 字符串是大多数编程语言中最常用最有用的数据类型,这在Linux shell编程中也不例外。 本文讨论了Linux Shell编程中的字符串的三种定义方式的差别,以及字符串拼接、取字符串长度、提取字符串、查找子字符串等常用字符串操作,,以及反…

【2023年11月第四版教材】第18章《项目绩效域》(合集篇)

第18章《项目绩效域》(合集篇) 1 章节内容2 干系人绩效域2.1 绩效要点2.2 执行效果检查2.3 与其他绩效域的相互作用 3 团队绩效域3.1 绩效要点3.2 与其他绩效域的相互作用3.3 执行效果检查3.4 开发方法和生命周期绩效域 4 绩效要点4.1 与其他绩效域的相互…

20231005使用ffmpeg旋转MP4视频

20231005使用ffmpeg旋转MP4视频 2023/10/5 12:21 百度搜搜:ffmpeg 旋转90度 https://zhuanlan.zhihu.com/p/637790915 【FFmpeg实战】FFMPEG常用命令行 https://blog.csdn.net/weixin_37515325/article/details/127817057 FFMPEG常用命令行 5.视频旋转 顺时针旋转…

System Generator学习——时间和资源分析

文章目录 前言一、目标二、步骤三、步骤 1 :系统生成器的时序分析1、时序分析2、解决时间违规问题 四、步骤 2 :系统生成器中的资源分析总结 前言 在本节实验中,你将学习如何通过在 Simulink 中进行仿真来验证设计的功能,以确保在…

熟练掌握Junit5框架

目录 一、注解 1.1 @Test 1.2 @Disabled 1.3 @BeforeAll 1.4 @AfterAll 1.5 @BeforeEach 1.6 @AfterEach 二、参数化 2.1单参数获取数据 2.2 CSV获取参数 2.3 方法获取数据 2.4 多参数获取数据 2.5测试用例执行顺序 2.6断言 2.6.1断言相等 2.6.2断言不相等

vue3使用v-model控制子组件进行双向数据绑定

vue2写法: 中父组件调用子组件: <child :isShow.sync"isShow" v-show"isShow"/> 子组件想要消失, 在子组件写: this.$emit("update:isShow",false); 具体代码就不粘贴了 vue3写法: 父组件核心代码: v-model:a"xxx" 子组…

aardio 读取 Excel文件,显示在 listview 中

编写 main.aardio 如下 import win.ui; /*DSG{{*/ winform win.form(text"excel1";right801;bottom500) winform.add( button1{cls"button";text"读取Excel文件";left19;top14;right126;bottom44;z1}; button2{cls"button";text&quo…

力扣第226翻转二叉数 c++三种方法 +注释

题目 226. 翻转二叉树 简单 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&am…

常见的几种排序方式

常见的几种排序方式 1. 排序的概念2. 常见排序算法的实现2.1 插入排序2.1.1基本思想2.1.2 直接插入排序2.1.3 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1基本思想2.2.2 直接选择排序:2.2.3 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序 2.4 归并排序2.4.1 基本思想2.4.2 …

【POST请求-腾讯翻译君-爬虫案例】

原因&#xff1a;尝试多个在线翻译平台&#xff0c;由于返回数据存在加密原因&#xff08;暂时不会解密&#xff09;&#xff0c;最总找到 ”腾讯翻译君“ 完成爬虫案例POST请求测试 案例测试网址 腾讯翻译 &#xff1a;https://fanyi.qq.com/ import requests import jsoncla…

知识图谱小白入门(1):neo4j的安装与CQL的使用

文章目录 序一、安装neo4j1.1 下载neo4j1.2 安装JDK1.3 BUG&#xff1a;dbms failed to start 二、CQL语法2.1 CQL语法创建节点查询节点创建关系查询关系2.2 习题 习题答案 序 知识图谱&#xff0c;是一种实体间的信息与关系知识的网状结构&#xff0c;借用图论中点与边的概念…

低代码开发技术选型

低代码的技术路径 低代码开发低代码开发优势低代码的技术路径1.表格驱动2.表单驱动3.数据模型4.领域模型 低代码的核心能力企业级低代码开发平台的11项关键能力低代码平台的流程引擎选型低代码平台的流程设计器选型低代码平台的表单设计器选型低代码平台的Vue.js 框架选型 低代…

python中的range的详解

一. python中的range的使用方法 range() 函数可创建一个整数列表&#xff0c;一般用在 for 循环中。 range(start, stop[, step])参数说明&#xff1a; start: 计数从 start 开始。默认是从 0 开始。例如range&#xff08;5&#xff09;等价于range&#xff08;0&#xff0c…