ElasticSearch分片与Lucene Index

Posted 心雨⁢​⁢⁣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch分片与Lucene Index相关的知识,希望对你有一定的参考价值。

        在ES中一个索引有一个或者多个分片构成,在创建索引的时候可以设置主分片和副本分片的数量,当主分片确定之后就不可以再修改了(因为路由需要基于这个数量来分发请求),而副本分片数量随时可以修改

PUT /myIndex

   "settings" : 
      "number_of_shards" : 2,    //该索引有2个分片
      "number_of_replicas" : 1   //每个分片都有一个副本
   

        这里我假设说是建立了两个节点,就是起了两个ES服务,shard1跟shard2就是创建的两个主分片,replica1和replica2就是两个副本分片,一般为了实现高可用,ES会将主分片和副本分片保存在不同的NODE节点中,这个动作由ES自动完成。

那么这一个个shard它又是什么呢?

shard = Lucene Index  

        我们知道ElasticSearch是一个分布式可扩展的实时搜索和分析引擎,是一个建立在全文搜索引擎Apache Lucene基础上的搜索引擎。那么Shard本质上就是一个个的Lucene Index。

        在lucene里面由很多小的segment,每个segment内部都有许多中数据结构,比如说经常听说的Inverted Index(倒排索引),Sorted Fields,Document Values...,那么其中最重要的就是倒排索引了。  

Inverted Index(倒排索引)

倒排索引主要包括两部分:

 当我们进行搜索的时候,会将搜索的内容进行分词。然后在字典找到对应的term,从而就可以找到搜索相关的文件内容。

  • 有序数据字典Dictionary(包括单词term和它出现的频率)

  • 与单词对应的Postings(即存在这个单词的文件)

Sorted Fields(字段查找)

当想要查找包含某个特定的标题内容的文档时,就会用到这种结构。本质上它是一个简单的K-V集合,默认会存储整个文档的Json格式。

网图:

Document Values(为了排序、聚合)

它是为了解决排序、聚合而诞生的。这种结构本质上是一个列式的存储。

网图:

 

为了提高效率、ES可以将索引下的某一个Document Vlaue 全部读取到内存中进行操作,以此来提高访问速度,但是会消耗内存空间。

这几种数据结构、Inverted Index、Sorted Fields、Document Values 以及缓存,都在Segment内部。

当搜索时

Lucene会搜索所有的segment,然后将每个segment的搜索结果返回,然后返回给客户端。

缓存

当ES搜索文档的时候,会给文档建立相应的缓存、并且每秒都去刷新缓存。  

segment合并

 随着时间的增加,会有越来越多的segment,es会将这些segment合并,合并之后将原来的删掉,所以就会出现一种情况,你增加了更多的文档,索引占用的空间可能越来越小,因为引起了merge,从而有更多的压缩。

文档索引步骤顺序

新建单个文档所需要的顺序步骤:

网图:

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

2,节点使用文档的_id确定文档属于那个分片。请求会被转发到对应的Node。

3,在分片上面执行请求。如果执行成功了,那么请求会被转发到各个节点的副本分片上,如果都成功了,那么就会返回给客户端成功的信息。

整体流程,依然是妄(网)图。。。

 

1,请求发送后会先来到协调节点,默认使用文档的id计算出来由哪一个分片来处理请求。

shard=hash(_id)%分片数量

2,分片接受到请求后,会先将请求写道memory buffer,然后定时(默认1s)写入到Filesystem。从memory buffer 到Filesystem cache的过程就叫refresh。

3,Transaction Log是用来保证数据可靠性的,因为refresh过程数据是有可能数据丢失的。在shard接受到请求后,同时会把请求写入translog中,当Filesystem cache中的数据写入到磁盘中后,才会被清除掉,这个过程教flush。

4,在flush过程中,内存中的缓存将会被清除,内容被写入一个新的段,段的fsync将会创建一个新的提交点,并将内容刷新到磁盘,旧的translog将被删除并开始一个新的trabslog。flush的触发机制默认30分钟,或者translog太大。

 

Elasticsearch的Refresh与Flush操作

初次接触到这两个概念,估计都会觉得他们没什么差别,都是为了在操作索引之后让索引可以被实时性的搜索,不过它们还是有点不同的。
Elasticsearch底层依赖Lucene,这里我们介绍下Lucene的segment, Reopen,commit。
Segment
在ES中,基本的存储单元是shard(分片),但是在更底层的Lucene上稍微有点不同,ES的每一个shard是Lucene的一个index(索引),Lucene的索引由多个segment组成,每个segment就是ES文档的倒序索引,里面包含了一些term(词)的mapping(映射)。

技术图片

当每个ES的文档创建的时候,都会写入一个新的segment中,因此每次写入的都是新的segment,所以不需要修改之前的segment。在删除文档的时候,只是在它属于的segment哪里标记为已删除就可,没有真正的从磁盘中抹除。更新也是同样的,只是在对应之前segment哪里标记为逻辑删除,然后新建一个新的segment。
Lucene Reopen
Reopen是为了让数据可以可以被搜索到,尽管这个时候数据可以被搜索到,但是不一定保证数据已经被持久化到磁盘中。
Lucene Commit
Commit就是为了让数据持久化,每一次的Commit,不同segment的数据都会被持久化到磁盘中,虽然这样可以让数据更安全,但是每一次操作都会消耗系统资源,会有大量的IO操作。
Translog
ES在持久化的时候引入了一种新的方式,translog(transaction log),一个文档被索引之后,就会被添加到内存缓冲区,并且 追加到了translog.

技术图片

ES的Refresh

默认情况下,ES会每秒refresh一次,每次操作都会把内存缓冲区的内容拷贝到新创建的segment中去,这一步是在内存中操作的,这个时候新的文档就会被搜索了。也就是说ES是近实时性的搜索,差不多1s钟,才能让数据可以被搜索到。
技术图片

ES的Flush

Flush操作意味着,所有在内存缓冲区的文档被写到新的Lucene Segment中,也就是所有在内存中的segment被提交到了磁盘,同时清除translog。

技术图片

一般Flush的时间间隔会比较久,默认30分钟,或者当translog达到了一定的大小,也会触发flush操作。

最后

简单来说,ES的refresh操作是为了让最新的数据可以立即被搜索到。而flush操作则是为了让数据持久化到磁盘中,另外ES的搜索是在内存中处理的,因此Flush操作不影响数据能否被搜索到。
translog一般在进行flush的时候被清空,一般在fsync和commit的时候被持久化到磁盘,默认的translog是在6.x版本以后,每次请求都会fsync到磁盘。不过有些index.translog的配置可以设置

以上是关于ElasticSearch分片与Lucene Index的主要内容,如果未能解决你的问题,请参考以下文章

高可用 Elasticsearch 集群的分片管理 (Shard)

Elasticsearch的Refresh与Flush操作

Elasticsearch分片大小和个数设计

elasticSearch理论篇—索引、节点、分片

ES分片副本设置及集群部署

ES分片副本设置及集群部署