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