以下是 ElasticSearch 面试题,相信大家都会有种及眼熟又陌生的感觉、看过可能在短暂的面试后又马上忘记了。JavaPub在这里整理这些容易忘记的重点知识及解答,建议收藏,经常温习查阅
。
评论区见
关于es的面试,建议使用名词用官方语言描述会更准确。
[toc]
节点数、分片数、副本数,尽量根据自己公司使用情况回答,当然适当放大也可行。
调优手段是现在很常见的面试题,下面这几种调优手段一定要了解懂。当然,下面的每一条都可以当做调优的一部分。
设计调优
参考:
https://www.cnblogs.com/sanduzxcvbnm/p/12084012.html
a. 根据业务增量需求,采取基于日期模板创建索引,通过 rollover API
滚动索引;(rollover API我会单独写一个代码案例做讲解,公众号:JavaPub)
b. 使用别名进行索引管理;(es的索引名不能改变,提供的别名机制使用非常广泛。)
c. 每天凌晨定时对索引做force_merge操作,以释放空间;
d. 采取冷热分离机制,热数据存储到SSD,提高检索效率;冷数据定期进行shrink操作,以缩减存储;
e. 采取curator进行索引的生命周期管理;
f. 仅针对需要分词的字段,合理的设置分词器;
g. Mapping阶段充分结合各个字段的属性,是否需要检索、是否需要存储等。
进100+原创文章:https://gitee.com/rodert/JavaPub
写入调优
查询调优
倒排索引也就是单词到文档的映射,当然不只是存里文档id这么简单。还包括:词频(TF,Term Frequency)、偏移量(offset)、位置(Posting)。
ElasticSearch 的选主是 ZenDiscovery 模块负责,源码分析将首发在。 https://gitee.com/rodert/JavaPub
一图胜千文,记住这幅图,上面是文档在节点间分发的过程,接着说一下文档从接收到写入磁盘过程。
协调节点默认使用文档 ID 参与计算(也支持通过 routing),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
1. translog 可以理解为就是一个文件,一直追加。 2. MemoryBuffer 应用缓存。 3. Filesystem Cache 系统缓冲区。
延伸阅读:Lucene 的 Segement
:
- Lucene 索引是由多个段组成,段本身是一个功能齐全的倒排索引。
- 段是不可变的,允许 Lucene 将新的文档增量地添加到索引中,而不用从头重建索引。
- 对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗CPU 的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。
- 为了解决这个问题,Elasticsearch 会合并小段到一个较大的段,提交新的合并段到磁盘,并删除那些旧的小段。
es作为一个分布式的存储和检索系统,每个文档根据 _id 字段做路由分发被转发到对应的shard上。
搜索执行阶段过程分俩个部分,我们称之为 Query Then Fetch。
5.1 query-查询阶段
当一个search请求发出的时候,这个query会被广播到索引里面的每一个shard(主shard或副本shard),每个shard会在本地执行查询请求后会生成一个命中文档的优先级队列。
这个队列是一个排序好的top N数据的列表,它的size等于from+size的和,也就是说如果你的from是10,size是10,那么这个队列的size就是20,所以这也是为什么深度分页不能用from+size这种方式,因为from越大,性能就越低。
es里面分布式search的查询流程如下:
查询阶段包含以下三个步骤:
5.2 fetch - 读取阶段 / 取回阶段
分布式阶段由以下步骤构成:
协调节点首先决定哪些文档 确实 需要被取回。例如,如果我们的查询指定了 { “from”: 90, “size”: 10 } ,最初的90个结果会被丢弃,只有从第91个开始的10个结果需要被取回。这些文档可能来自和最初搜索请求有关的一个、多个甚至全部分片。
协调节点给持有相关文档的每个分片创建一个 multi-get request ,并发送请求给同样处理查询阶段的分片副本。
分片加载文档体-- _source 字段—如果有需要,用元数据和 search snippet highlighting 丰富结果文档。 一旦协调节点接收到所有的结果文档,它就组装这些结果为单个响应返回给客户端。
拓展阅读: 深翻页(Deep Pagination) --- 先查后取的过程支持用 from 和 size 参数分页,但是这是 有限制的 。 要记住需要传递信息给协调节点的每个分片必须先创建一个 from + size 长度的队列,协调节点需要根据 number_of_shards * (from + size) 排序文档,来找到被包含在 size 里的文档。 取决于你的文档的大小,分片的数量和你使用的硬件,给 10,000 到 50,000 的结果文档深分页( 1,000 到 5,000 页)是完全可行的。但是使用足够大的 from 值,排序过程可能会变得非常沉重,使用大量的CPU、内存和带宽。因为这个原因,我们强烈建议你不要使用深分页。 实际上, “深分页” 很少符合人的行为。当2到3页过去以后,人会停止翻页,并且改变搜索标准。会不知疲倦地一页一页的获取网页直到你的服务崩溃的罪魁祸首一般是机器人或者web spider。 如果你 确实 需要从你的集群取回大量的文档,你可以通过用 scroll 查询禁用排序使这个取回行为更有效率,我们会在 later in this chapter 进行讨论。 注:https://www.elastic.co/guide/cn/elasticsearch/guide/current/scroll.html
原因:大多数操作系统会将内存使用到文件系统缓存,会将应用程序未用到的内存交换出去。会导致jvm的堆内存交换到磁盘上。交换会导致性能问题。会导致内存垃圾回收延长。会导致集群节点响应时间变慢,或者从集群中断开。
堆内存设置为:Min(节点内存/2, 32GB);
设置最大文件句柄数;
后俩点不懂可以先说有一定了解,关注JavaPub会做详细讲解。
调整线程池和队列大小
磁盘存储 raid 方式——存储有条件使用 RAID6,增加单节点性能以及避免单节点存储故障。
https://www.elastic.co/cn/blog/how-to-design-your-elasticsearch-data-storage-architecture-for-scale#raid56
当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data节点,避免脑裂问题。
client 远程连接连接一个 elasticsearch 集群。它并不加入到集群中,只是获得一个或者多个初始化的地址,并以轮询的方式与这些地址进行通信。
.del
文件中被标记为删除。该文档依然能匹配查询,但是会在 结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入 新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
这道题目较难,相信大家看到很多类似这种回答
Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。
科普&拓展:
HyperLogLog: 下面简称为HLL,它是 LogLog 算法的升级版,作用是能够提供不精确的去重计数。存在以下的特点: 1. 能够使用极少的内存来统计巨量的数据,在 Redis 中实现的 HyperLogLog,只需要12K内存就能统计2^64个数据。 2. 计数存在一定的误差,误差率整体较低。标准误差为 0.81% 。 3. 误差可以被设置辅助计算因子进行降低。 --- 应用场景: 1. 基数不大,数据量不大就用不上,会有点大材小用浪费空间 2. 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么 3. 和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多 4. 一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数 --- 应用场景: 1. 基数不大,数据量不大就用不上,会有点大材小用浪费空间 2. 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么 3. 和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多 4. 一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数 来源:刷刷面试
首先要了解什么是一致性,在分布式系统中,我们一般通过CPA理论分析。
分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。
如果你没有很多实战经验,可以基于 word2vec 做一些练习,我的博客提供了 word2vec Java版的一些Demo。
基于 word2vec 和 Elasticsearch 实现个性化搜索,它有以下优点: