ES常见问题3:架构特点

参考:

https://developer.aliyun.com/article/879525(10道不得不会的ElasticSearch面试题)

https://blog.csdn.net/QLCZ0809/article/details/124821823(30道你不得不会的Elasticsearch面试题)

https://zhuanlan.zhihu.com/p/338068831(ElasticSearch 原理解析)

倒排索引结构

Lucene的核心就是倒排索引(Inverted Index),倒排索引是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。
Lucene会将文档分成一个一个的Term(单词),然后建立倒排索引。首先让我们先来看看倒排索引的结构:

 

1,Term Index:Lucene使用FST实现Term Index,Term Index是Term Dictionary的索引,可以快速查找一个Term是否在Dictionary中;并且能够快速定位Block的位置。lucene 从 4+版本后开始大量使用的数据结构是 FST

2,Term Dictionary:Segment的字典

3,Postings:记录了出现过的某个Term的文档列表及该Term在文档中出现的位置信息(Payload)

Payload的作用:
1,存储每个文档都有的信息
2,影响词的评分

Lucene使用FST(Finite State Transducer)实现,FST类似字典树,但与字典树又有很大的不同,FST有如下特点:

共享前缀
共享后缀
确定
无环
Transducer:接收特定的序列,终止于Final状态,同时会输出一个值

 

索引创建流程:

1,索引请求首先会发送到Client Node,Client Node会根据路由规则将请求转发到Data Node(Primary Shard)进行处理(Parimary Shard所在的Data Node从Master Node获取)

shard = hash(document_id) % (num_of_primary_shards)

2,Primary Shard会往Lucene写,写成功后会再写到Translog(Translog是ElasticSearch为了提高可靠性引入的,因为Lucene首先会先写内存,如果宕机了数据就丢了),然后会将广播到Replica Shard进行处理

3,在所有的Replica Shard都写成功后则返回给用户成功索引数据

举例如下:

1,客户端向 Node 1 发送新建、索引或者删除请求。

2,节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在 Node 3 上。

3,Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。

文档在节点间分发的过程,接着说一下文档从接收到写入磁盘过程

1,当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 MemoryBuffer,然后定时(默认是每隔 1 秒)写入到 Filesystem Cache,这个从 MomeryBuffer 到 Filesystem Cache 的过程就叫做 refresh;

2,当然在某些情况下,存在 Momery Buffer 和 Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush;

3,在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。

4,flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512M)时;

 

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

1,删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;(根本原因是底层lucene的segment段文件不可更新删除)

2,磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真 的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在 结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入 新段。

3,在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新 时,旧版本的文档在.del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。

 

ElasticSearch搜索流程:

es作为一个分布式的存储和检索系统,每个文档根据 _id 字段做路由分发被转发到对应的shard上。

搜索执行阶段过程分俩个部分:query和fetch

query阶段

1,客户端发送一个 search 请求到协调结点Node3 , Node3会创建一个优先队列

2,Node3 将查询请求转发到索引的每个主分片或副本分片中。每个分片在本地执行查询并添加结果本地有序优先队列中。

3,每个分片返回各自优先队列中所有文档的 ID 和排序值给协调节点Node3,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表

fetch阶段

1,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。

2,每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。

3,一旦所有的文档都被取回了,协调节点返回结果给客户端。

 

ElasticSearch 搜索常见技巧

Index Mapping

Index Mapping是对索引的字段名称跟数据类型等的定义,类似于MySQL中的表结构信息。可以通过Mapping定义使用的分词器、是否分词、是否存储等等。

Index Setting

Index Setting是索引的设置,可以指定索引的Shard数跟Replicas数等。

索引别名

索引别名就像一个快捷方式或软连接,可以指向一个或多个索引。
利用索引别名机制,我们可以按月或按年建索引,使用别名关联多个索引,然后就可以灵活地选择索引的过期时间

Rollover

通过ElasticSearch的Rollover机制,可以在索引满足一个的条件后新建索引,并将索引别名转向新索引。可以设置的Rollover条件有:

max_age:索引最大存活时间
max_docs:索引最大文档数
max_size:索引最大大小

索引模板

索引模板 + Rollover机制 + 索引别名机制 可以实现自动创建索引,在我们需要对数据进行过期处理时这几个特性联合使用非常强大。
索引模板在索引创建时会自动应用到索引上。

分页

由于ElasticSearch是分布式的,查找第一页数据需要所有Shard都返回第一页的数据,然后由Client Node进行聚合跟排序,最后只将一页的结果返回给用户。因此ElasticSearch深度分页会随着分页的深度成指数上升,不建议查询分页太大。
 

ES调优手段

设计调优

根据业务增量需求,采取基于日期模板创建索引,通过 rollover API 滚动索引;
使用别名进行索引管理;(es的索引名不能改变,提供的别名机制使用非常广泛。)
每天凌晨定时对索引做force_merge操作,以释放空间;
采取冷热分离机制,热数据存储到SSD,提高检索效率;冷数据定期进行shrink操作,以缩减存储;
取curator进行索引的生命周期管理;
f仅针对需要分词的字段,合理的设置分词器; 
Mapping阶段充分结合各个字段的属性,是否需要检索、是否需要存储等。

写入调优

写入前副本数设置为0;
写入前关闭refresh_interval设置为-1,禁用刷新机制;
写入过程中:采取bulk批量写入;
写入后恢复副本数和刷新间隔;
尽量使用自动生成的id。

查询调优

禁用wildcard;(通配符模式,类似于%like%)
禁用批量terms(成百上千的场景);
充分利用倒排索引机制,能keyword类型尽量keyword;

ES部署时Linux系统设置调优

1,关闭swap
2,设置最大文件句柄数
3,堆内存设置:节点内存/2

 

ES怎样进行master选举

1,Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个 RPC 来发 现彼此)和 Unicast(单播模块包含一个主机列表)这两部分;

2,对所有可以成为 master 的节点(node.master: true)根据 nodeId 字典排序,每次选举每个节 点都把自己所知道节点排一次序,然后选出第一个(第 0 位)节点,暂且认为它是 master 节点。

3,如果对某个节点的投票数达到一定的值(可以成为 master 节点数 n/2+1)并且该节点自己也选 举自己,那这个节点就是 master。否则重新选举一直到满足上述条件。

避免脑裂

1,当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;

2,当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data节点,避免脑裂问题。

 

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

1,倒排词典的索引需要常驻内存,无法 GC,需要监控 data node 上 segmentmemory 增长趋势

2,各类缓存:indexing cache, bulk queue 等等,要设置合理的大小

3,避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api来实现

 

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

1,可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;

2,另外对于写操作,一致性级别支持 quorum/one/all设置为quorum(默认),即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。

3,对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;

 

拼写纠错是如何实现的

拼写纠错是基于编辑距离来实现

 

如何监控 Elasticsearch 集群状态

通过 Kibana 监控 Elasticsearch

 

Lucene 的segment

 

1,Lucene 索引是由多个段组成,段本身是一个功能齐全的倒排索引。

2,段是不可变的,允许 Lucene 将新的文档增量地添加到索引中,而不用从头重建索引。

3,对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗CPU 的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。

4,为了解决这个问题,Elasticsearch 会合并小段到一个较大的段,提交新的合并段到磁盘,并删除那些旧的小段。

什么是段合并?段合并的时候会将那些旧的已删除文档从文件系统中清除。

1,由于自动刷新流程每秒会创建一个新的段(由动态配置参数:refresh_interval 决定),这样会导致短时间内的段数量暴增。Elasticsearch 通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

3,启动段合并不需要你做任何事。进行索引和搜索时会自动进行。

force_merge的api操作

参考:https://blog.csdn.net/vincent_duan/article/details/109318299

查看某个index的forceMerge情况 
GET /_cat/segments/myindex?v&s=prirep,shard

首先查看我们的index(可以使用正则匹配)当前有多少个segment:
GET _cat/segments/myindex?v&h=shard,segment,size,size.memory

执行forcemerge:
POST myindex/_forcemerge?max_num_segments=1 //这个过程可能执行的时间比较久。

 

集群,节点,索引,分片,段的关系

一个集群包含1个或多个节点;

一个节点包含1个或多个索引;

每个索引类似 Mysql 中的数据库,又由一个或多个分片组成;

每个分片都是一个 Lucene 索引实例,您可以将其视作一个独立的搜索引擎,它能够对 Elasticsearch 集群中的数据子集进行索引并处理相关查询;

每个分片包含多个segment(段),每一个segment都是一个倒排索引。

 

索引翻滚 Rollover Index

参考:https://blog.csdn.net/weixin_43820556/article/details/122072407

 

分词器:

参考:https://www.jianshu.com/p/65bcac286012(ES内置分词器)

分词器是ES中专门处理分词的组件,英文为Analyzer,它的组成如下:

Character Filters:针对原始文本进行处理,比如去除html标签
Tokenizer:将原始文本按照一定规则切分为单词
Token Filters:针对Tokenizer处理的单词进行再加工,比如转小写、删除或增新等处理

内置分词器

Standard Analyzer:默认
Whitespace Analyzer:空白分隔符
Keyword Analyzer:不分词
Language Analyzers:语言分词

eg
POST _analyze
{
  "analyzer": "standard",//修改分词器类型
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

中文分词器:

使用较多的中文分词器是 elasticsearch-analysis-ik,这个是 es 的一个第三方插件,代码托管在 GitHub 上

 

posted @ 2022-07-17 17:17  小匡程序员  阅读(228)  评论(0编辑  收藏  举报