一、原理篇
Elasticsearch 的倒排索引是什么?
倒排索引=term字典+docId倒排表,term字典基于FST(有限状态转换器),docId检索基于SkipList(跳表)。
详细描述一下 Elasticsearch 索引(写入)文档的过程(集群层面)。
宏观上,此图可以概括:三步写入,1、向节点发送请求,2、根据文档Id路由请求,3、先主后副,成功后再返回。副本的ACK虽然导致写入性能降低,但是数据可靠性提升。
文档写入其中:文档获取分片的过程是借助路由算法获取,路由算法就是根据路由和文档 id 计算目标的分片 id 的过程。
1shard = hash(_routing) % (num_of_primary_shards)
详细描述一下 Lucene 索引(写入)文档的过程(内核层面)。
上述多副本解决了单点故障问题,但当Lucene从内存刷入磁盘如何保证数据可靠性,类似数据库的的CommitLog模块,Elasticsearch引入TransLog。
Refresh && Flush写入请求到达Shard后,先写Lucene文件,创建好索引,此时索引还在内存里面,接着去写TransLog,写完TransLog后,刷新TransLog数据到磁盘上,写磁盘成功后,请求返回给用户。
注意:写Lucene内存后,并不是可被搜索的,再次refresh后才能被搜索——即通过Refresh把内存的对象转成完整的Segment后(文件系统缓存中),一般这个时间设置为1秒钟,导致写入Elasticsearch的文档,最快要1秒钟才可被从搜索到,所以Elasticsearch在搜索方面是NRT(Near Real Time)近实时的系统。
进行一次提交并删除事务日志的操作叫做 flush 。分片每30分钟,或事务日志过大会进行一次flush操作。
详细描述一下 Elasticsearch 更新和删除文档的过程。
Segment段是不可变的,所以文档不能从旧的段中删除,旧的段也不能进行更新,所以每个提交点(commit point)包含了段上一个.del文件,里面为段上被删除的文档。被删除的文档和被更新的文档,旧文档被标记为删除,但依然可以匹配查询,但最终的返回之前会被从结果中删除。
详细描述一下 Elasticsearch 搜索的过程
- 搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
- 在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。
PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 MemoryBuffer,所以搜索是近实时的。 - 每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
- 接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰 富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
- 补充:Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。
Elasticsearch 是如何实现 master 选举的
bully选举算法。其主要思路是对节点ID进行排序,取ID值最大的为Master,每个节点都会运行这个过程。选完主节点以后,才会再去把最新的机器元数据复制到选举出的主节点上。基于节点ID排序的简单选举算法有三个附加约定条件:
- 参选人数需超过quorum值
- 得票数需过quorum值
- 当探测到节点离开事件时候,必须要判断当前的节点数是否过quorum值。
集群刚启动的时候,并不知道自己有多少个节点吗,因此quorum值是根据配置文件中discovery.zen.minium_master_nodes
配置值来的。
客户端在和集群连接时,如何选择特定的节点执行请求的?
TransportClient 利用 transport 模块远程连接一个 elasticsearch 集群。它并不加入到集群中,只是简单的获得一个或者多个初始化的 transport 地址,并以轮询 的方式与这些地址进行通信。
是否了解字典树
term字典采用的为FST数据结构:
常见词典的优缺点拼写纠错是如何实现的
拼写纠错是基于编辑距离来实现;编辑距离是一种标准的方法,它用来表示经过插入、删除和替换操作从一个字符串转换到另外一个字符串的最小操作步数;
二、实战篇
Elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段 。
业务系统:3主3数据,
- 主节点:4c8g,200g;
- 数据节点:16c32g,500g
日志系统:3主3协调6数据节点
- master 4c 16g
- client 12c 32g
- data 24c 64g 2T
对于 GC 方面,在使用 Elasticsearch 时要注意什么?
避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api 来实现。
如何监控 Elasticsearch 集群状态?
Kibana 监控 Elasticsearch。可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标。
介绍下你们搜索的整体技术架构。
介绍一下你们的个性化搜索方案?
- 暂时未精确到用户,从搜索量进行整合排序放在推荐列。
- 结合自然语言处理,进行语义分析和实体抽取,放到不同的槽位进行提取。
- 基于word2vec、Elasticsearch和自定义的脚本插件,我们就实现了一个个性化的搜索服务,相对于原有的实现,新版的点击率和转化率都有大幅的提升;
三、优化篇
设计阶段的常见调优手段
1.1、设计阶段调优
(1)根据业务增量需求,采取基于日期模板创建索引,通过 roll over API 滚动索引;
(2)使用别名进行索引管理;
(3)每天凌晨定时对索引做 force_merge 操作,以释放空间;
(4)采取冷热分离机制,热数据存储到 SSD,提高检索效率;冷数据定期进行 shrink操作,以缩减存储;
(5)采取 curator 进行索引的生命周期管理;
(6)仅针对需要分词的字段,合理的设置分词器;
(7)Mapping 阶段充分结合各个字段的属性,是否需要检索、是否需要存储等。……..
1.2、写入调优
(1)写入前副本数设置为 0;
(2)写入前关闭 refresh_interval 设置为-1,禁用刷新机制;
(3)写入过程中:采取 bulk 批量写入;
(4)写入后恢复副本数和刷新间隔;
(5)尽量使用自动生成的 id。
1.3、查询调优
(1)禁用 wildcard;
(2)禁用批量 terms(成百上千的场景);
(3)充分利用倒排索引机制,能 keyword 类型尽量 keyword;
(4)数据量大时候,可以先基于时间敲定索引再检索;
(5)设置合理的路由机制。
1.4、其他调优
部署调优,业务调优等。
Elasticsearch 索引数据多了怎么办,如何调优,部署
1.动态索引层面
基于模板+时间+rollover api 滚动创建索引,举例:设计阶段定义:blog 索引的模板格式为:blog_index_时间戳的形式,每天递增数据。这样做的好处:不至于数据量激增导致单个索引数据量非常大,接近于上线 2 的32 次幂-1,索引存储达到了 TB+甚至更大。
一旦单个索引很大,存储等各种风险也随之而来,所以要提前考虑+及早避免。
2.存储层面
冷热数据分离存储,热数据(比如最近 3 天或者一周的数据),其余为冷数据。
对于冷数据不会再写入新数据,可以考虑定期 force_merge 加 shrink 压缩操作,节省存储空间和检索效率。
3.部署层面
一旦之前没有规划,这里就属于应急策略。
结合 ES 自身的支持动态扩展的特点,动态新增机器的方式可以缓解集群压力,注意:如果之前主节点等规划合理,不需要重启集群也能完成动态新增的。
Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法
- 关闭缓存 swap;
- 堆内存设置为:Min(节点内存/2, 32GB);
- 设置最大文件句柄数;
- 线程池+队列大小根据业务需要做调整;
- 磁盘存储 raid 方式——存储有条件使用 RAID10,增加单节点性能以及避免单节点存储故障。
Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?
Elasticsearch 提供的首个近似聚合是 cardinality 度量。它提供一个字段的基数,即该字段的 distinct 或者 unique 值的数目。它是基于 HLL 算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。
在并发情况下,Elasticsearch 如果保证读写一致?
(1)可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
(2)另外对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。
(3)对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置 replication 为 async 时,也可以通过设置搜索请求参数_preference 为 primary 来查询主分片,确保文档是最新版本。
source: 常见Elasticsearch 面试题答案详细解析
网友评论