Elasticsearch
Elasticsearch
1.elasticsearch 的倒排索引是什么
传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。 而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。有了 倒排索引,就能实现 o(1)时间复杂度的效率检索文章了,极大的提高了检索效率。
学术的解答方式: 倒排索引,相反于一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成——词典和倒排表。
加分项:倒排索引的底层实现是基于:FST(Finite State Transducer)数据结构。
lucene 从 4+版本后开始大量使用的数据结构是 FST。
FST 有两个优点:
(1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;
(2)查询速度快。O(len(str))的查询时间复杂度。
2.Elasticsearch 的 master 选举流程?
Elasticsearch 的选举是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个 RPC 来发现彼此) 和 Unicast(单播模块包含一个主机列表以控制哪些节点需要 ping 通)这两部分
对所有可以成为 master 的节点(node.master: true)根据 nodeId 字典排序,每次选举每个节点都把自 己所知道节点排一次序,然后选出第一个(第 0 位)节点,暂且认为它是 master 节点。
如果对某个节点的投票数达到一定的值(可以成为 master 节点数 n/2+1)并且该节点自己也选举自己, 那这个节点就是 master。否则重新选举一直到满足上述条件。
master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。
3.为什么要使用 Elasticsearch?
系统中的数据,随着业务的发展,时间的推移,将会非常多,而业务中往往采用模糊查询进行数据的 搜索,而模糊查询会导致查询引擎放弃索引,导致系统查询数据时都是全表扫描,在百万级别的数据库中, 查询效率是非常低下的,而我们使用 ES 做一个全文索引,将经常查询的系统功能的某些字段,比如说电 商系统的商品表中商品名,描述、价格还有 id 这些字段我们放入 ES 索引库里,可以提高查询速度。
4.Elasticsearch 集群脑裂问题?
“脑裂”问题可能的成因:
网络问题 :集群间的网络延迟导致一些节点访问不到 master ,认为 master 挂掉了从而选举出新的master,并对 master 上的分片和副本标红,分配新的主分片
节点负载:主节点的角色既为 master 又为 data,访问量较大时可能会导致 ES 停止响应造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。
内存回收:data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应。
脑裂问题解决方案:
减少误判:discovery.zen.ping_timeout 节点状态的响应时间,默认为 3s,可以适当调大,如果 master在该响应时间的范围内没有做出响应应答, 判断该节点已经挂掉了。 调大参数(如 6s ,discovery.zen.ping_timeout:6),可适当减少误判。
选举触发: discovery.zen.minimum_master_nodes:1
该参数是用于控制选举行为发生的最小集群主节点数量。当备选主节点的个数大于等于该参数的值, 且备选主节点中有该参数个节点认为主节点挂了,进行选举。官方建议为(n/2)+1,n 为主节点个数 (即有资格成为主节点的节点个数)
角色分离:即 master 节点与 data 节点分离,限制角色
主节点配置为:node.master: true node.data: false 从节点配置为:node.master: false node.data: true
5.Elasticsearch 索引文档的流程?
这里的索引文档应该理解为文档写入 ES,创建索引的过程。 文档写入包含:单文档写入和批量 bulk 写入。
协调节点默认使用文档 ID 参与计算(也支持通过 routing),以便为路由提供合适的分片: shard = hash(document_id) % (num_of_primary_shards)
当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认 是每隔 1 秒)写入到 Filesystem Cache,这个从 Memory Buffer 到 Filesystem Cache 的过程就叫做 refresh;
当然在某些情况下,存在 Momery Buffer 和 Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush;
在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync 将创建一个新的提交点, 并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。
flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512M)时;
分片所在的节点 在主分片上执行写操作,如果成功,则将请求并行转发到其他节点的副本分片 上,等待结果返回。所有的副本分片都报告成功,节点将向协调节点报告成功,协调节点向请求客户端报告写入成功。
6.Elasticsearch 更新和删除文档的流程?
删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;
磁盘上的每个段都有一个相应的.del 文件。当删除请求发送后,文档并没有真的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入新段。
在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结 果中被过滤掉。
7.Elasticsearch 搜索的流程?
搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。 PS :在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的。
每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队 列中来产生一个全局排序后的结果列表。 接下来就是取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每 个分片加载并丰富文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了, 协调节点返回结果给客户端。
Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少 的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。
8.在并发情况下,Elasticsearch 如果保证读写一致?
可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
另外对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故 障,分片将会在一个不同的节点上重建。
对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回; 如果设置 replication 为 async 时,也可以通过设置搜索请求参数_preference 为 primary 来查询主分片, 确保文档是最新版本。
9.Elasticsearch 中的集群、节点、索引、文档、类型是什么?
集群是一个或多个节点(服务器)的集合,它们共同保存您的整个数据,并提供跨所有节点的联合索引和搜索功能。集群由唯一名称标识,默认情况下为“elasticsearch”。此名称很重要,因为如果节点设置为按名称加入集群,则该节点只能是集群的一部分。
节点是属于集群一部分的单个服务器。它存储数据并参与集群索引和搜索功能。
索引就像关系数据库中的“数据库”。它有一个定义多种类型的映射。索引是逻辑名称空间,映射到一 个或多个主分片,并且可以有零个或多个副本分片。 MySQL =>数据库 Elasticsearch =>索引
文档类似于关系数据库中的一行。不同之处在于索引中的每个文档可以具有不同的结构(字段),但 是对于通用字段应该具有相同的数据类型。 MySQL => Databases => Tables => Columns / Rows Elasticsearch => Indices => Types =>具有属性的文档
类型是索引的逻辑类别/分区,其语义完全取决于用户。
10.说说分段存储的思想
Lucene 是著名的搜索开源软件,ElasticSearch 和 Solr 底层用的都是它。
分段存储是 Lucene 的思想。 早期,都是一个整个文档建立一个大的倒排索引。简单,快速,但是问题随之而来。 文档有个很小的改动,整个索引需要重新建立,速度慢,成本高,为了提高速度,定期更新那么时 效性就差。 现在一个索引文件,拆分为多个子文件,每个子文件是段。修改的数据不影响的段不必做处理。
11.谈谈你对段合并的策略思想的认识
分段的思想大大的提高了维护索引的效率。但是随之就有了新的问题。 每次新增数据就会新增加一个段,时间久了,一个文档对应的段非常多。段多了,也就影响检索性 能了。 检索过程:
查询所有短中满足条件的数据
对每个段的结果集合并
所以,定期的对段进行合理是很必要的。真是天下大势,分久必合合久必分。 策略:将段按大小排列分组,大到一定程度的不参与合并。小的组内合并。整体维持在一个合理的 大小范围。当然这个大到底应该是多少,是用户可配置的。这也符合设计的思想。
12.熟悉ElasticSearch 性能优化?
- 批量提交
背景是大量的写操作,每次提交都是一次网络开销。网络永久是优化要考虑的重点。
- 优化硬盘
索引文件需要落地硬盘,段的思想又带来了更多的小文件,磁盘 IO 是 ES 的性能瓶颈。一个固态硬 盘比普通硬盘好太多。
- 减少副本数量
副本可以保证集群的可用性,但是严重影响了 写索引的效率。写索引时不只完成写入索引,还要完 成索引到副本的同步。ES 不是存储引擎,不要考虑数据丢失,性能更重要。 如果是批量导入,建 议就关闭副本。
13.node一般设置几个分片?
我们遵循官方建议,一般node不多于3个分片。