1. elasticsearch 了解多少,说说你们公司 es 的集群架构,节点,分片有多少,以及一些调优手段 ?
ES 集群架构有3个节点,主分片数:5;复制分片数:5
教学资源推荐:resource-api es 节点数 3 主分片:5,复制分片5 数据量大小:511万,主分片存储数据量2.6g
题库资源:quest-api es 节点数 3 主分片:5,复制分片5 数据量大小:1186万,主分片存储数据量5.1g
调优手段:
设计阶段调优
根据业务增量需求,采取基于日期模板创建索引,通过 roll over API 滚动索引;
每天凌晨定时对索引做 force_merge 操作,以释放空间;
采取冷热分离机制,热数据存储到 SSD,提高检索效率;冷数据定期进行 shrink操作,以缩减存储;
采取 curator 进行索引的生命周期管理;
仅针对需要分词的字段,合理的设置分词器;
Mapping 阶段充分结合各个字段的属性,合理设置字段类型(比如不分词的字段设置为keyword)
写入调优
1、写入前副本数设置为 0;
2、写入前关闭 refresh_interval 设置为-1,禁用刷新机制;
3、写入过程中:采取 bulk 批量写入;
4、写入后恢复副本数和刷新间隔;
5、尽量使用自动生成的 id。
查询调优
- 1、禁用 wildcard(通配符模糊查询);
- 2、禁用批量 terms(成百上千的场景);
- 3、充分利用倒排索引机制,能 keyword 类型尽量 keyword;
- 4、设置合理的路由机制。
2. elasticsearch 的倒排索引是什么?
传统的检索方式是通过文章,逐个遍历找到对应关键词的位置。
倒排索引,是通过分词策略,形成了词和文章的映射关系表,也称倒排表,这种词典 + 映射表即为倒排索引。
其中词典中存储词元,倒排表中存储该词元在哪些文中出现的位置。
有了倒排索引,就能实现 O(1) 时间复杂度的效率检索文章了,极大的提高了检索效率。
倒排索引的底层实现是基于:FST(Finite State Transducer)有限状态转移器 数据结构。
3. ES是如何实现master选举的?
- 确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes;
- 对所有候选主节点根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
- 如果对某个节点的投票数达到一定的值(候选主节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。
4. 如何解决ES集群的脑裂问题
所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。
- 当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
- 当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data 节点,避免脑裂问题。
5. ES文档写入过程?
客户端向集群某节点写入数据,发送请求
协调节点接受到请求后,默认使用文档 ID 参与计算,得到该文档属于哪个分片。随后请求会被转到另外的节点。
shard = hash(document_id) % (num_of_primary_shards)
当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认是每隔 1 秒)写入到F ilesystem Cache,这个从 Momery Buffer 到 Filesystem Cache 的过程就叫做 refresh;
当然在某些情况下,存在 Memery Buffer 和 Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush;
在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync 将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。
flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512 M)时。
6. 详细描述一下ES更新和删除文档的过程?
- 删除
删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更。
磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在 .del 文件中被标记为删除的文档将不会被写入新段。
- 更新
在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在 .del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
7. 详细描述一下ES搜索的过程?
搜索被执行成一个两阶段过程,即 Query Then Fetch;
Query阶段:
查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询Filesystem Cache的,但是有部分数据还在Memory Buffer,所以搜索是近实时的。 每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
Fetch阶段:
协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
8. 索引是什么?
ES集群包含多个索引,每个索引包含一种表,表包含多个文档,并且每个文档包含不同的属性。
9. 请解释什么是分片(SHARDs)?
随着索引文件的增加,磁盘容量、处理能力都会变得不够,在这种情况下,将索引数据切分成小段,这就叫分片(SHARDS)。它的出现大大改进了数据查询的效率。
10. 什么是副本(REPLICA), 他的作用是什么?
副本是分片的完整拷贝,副本的作用是增加了查询的吞吐率和在极端负载情况下获得高可用的能力。副本有效的帮助处理用户请求。
11. 在ES集群中增加和创建索引的步骤是什么?
可以在Kibana中配置新的索引,进行Fields Mapping,设置索引别名。也可以通过HTTP请求来创建索引。
12. ES支持哪些类型的查询?
主要分为匹配(文本)查询和基于Term的查询。
文本查询包括基本匹配,match phrase, multi-match, match phrase prefix, common terms, query-string, simple query string.
Term查询,比如term exists, type, term set, range, prefix, ids, wildcard, regexp, and fuzzy。
13. 在并发情况下,ES如果保证读写一致?
可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突; 另外对于写操作,一致性级别支持quorum/one/all,默认为quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。 对于读操作,可以设置replication为sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication为async时,也可以通过设置搜索请求参数_preference为primary来查询主分片,确保文档是最新版本。
14. ES对于大数据量(上亿量级)的聚合如何实现?
Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。