1.Elasticsearch索引

Elasticsearch之所以能够实现快速查询其中一点是因为它实现了全文索引,其底层依赖于 Lucene,而 Lucene 能实现全文搜索主要是因为它实现了倒排索引的查询结构。这里通过一个例子来讲解倒排索引。
假设有3份文档的内容如下:
第1份文档内容:Java is the best programming language.
第2份文档内容:PHP is the best programming language.
第3份文档内容:Javascript is the best programming language.
为了创建倒排索引,通过分词器将每个文档的内容拆分成单独的词(我们称它为词条或 Term),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。
如下表格所示:

Term(词条) 第1份文档 第2份文档 第3份文档
Java 存在

is 存在 存在 存在
the 存在 存在 存在
best 存在 存在 存在
programming 存在 存在 存在
language 存在 存在 存在
PHP
存在
Javascript

存在

上面的表格将每个词条在哪些文档中出现做了描述。
这种结构由文档中所有不重复词的列表构成,对于其中每个词都有一个文档列表与之关联。
这种由属性值来确定记录的位置的结构就是倒排索引。带有倒排索引的文件称为倒排文件。我们将上面的内容转换为图的形式来说明倒排索引的结构信息,如下图所示,我们将这几个概念进行解释:
其中主要有如下几个核心术语需要理解:

  • 词条(Term):索引里面最小的存储和查询单元,对于英文来说是一个单词比如best、is、Java等单词,对于中文来说一般指分词后的一个词比如我爱中国分词后,我,爱,中国,我爱中国。
  • 词典(Term Dictionary):或字典,是词条 Term 的集合,比如下图中best、is、Java这些词条组合成词典。搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息和指向“倒排列表”的指针(如下图best指向文档1,2,3的链表)。
  • 倒排表(Post list):一个文档通常由多个词组成,倒排表记录的是某个词在哪些文档里出现过以及出现的位置,如下图language单词对应的文档在1,2,3都存在,构建一个1-》2-》3的倒排表。
  • 倒排项(Posting):倒排表中每条记录称为倒排项。倒排表记录的不单是文档编号,还存储了词频等信息。
  • 倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件,倒排文件是存储倒排索引的物理文件。

02_Elasticsearch的核心原理介绍 - 图1

2.Elasticsearch分片

Elasticsearch支持PB级全文索引,当索引上的数据量太大的时候,Elasticsearch通过水平拆分的方式将一个索引上的数据拆分出来分配到不同的数据块上,拆分出来的数据块称之为一个分片。这样做的目的是让数据访问的时候,通过不同的分片规则去访问不同的数据分片,从而提高Elasticsearch的吞吐量。
这类类似于MYSQL的分库分表,只不过MYSQL分库分表需要借助第三方组件而Elasticsearch内部自身实现了此功能。
在一个多分片的索引中写入数据时,通过路由来确定具体写入哪一个分片中,所以在创建索引的时候需要指定分片的数量,并且分片的数量一旦确定就不能修改。如下代码所示,分片和副本的数量在创建索引时通过指定的Settings来配置,Elasticsearch默认为一个索引创建5个主分片,并为每一个分片创建一个副本。

  1. PUT /myIndex
  2. {
  3. "settings": {
  4. "number_of_shards": 5,
  5. "number_of_replicas": 1
  6. }
  7. }

3.Elasticsearch副本

副本就是分片拷贝,一个主分片有一个或多个副本分片,当主分片异常时,副本可以提供数据的查询等操作。主分片和对应的副本分片在es集群部署时是不会在同一个节点上的,所有副本分片数的最大值是N-1(其中N为节点数)。
创建索引、创建文档、更新文档、删除文档这些请求都是写操作,必须在主分片上完成之后才能被复制到相关的副本分片上。ES 为了提高写入的能力这个过程是并发写的,也就是说更新文档和删除文档不互斥,es底层为了解决并发写的数据冲突问题,通过乐观锁的方式控制,每个文档都有一个 _version版本号,当文档被修改时版本号递增。
一旦所有的副本分片都报告写成功才会向协调节点报告写操作成功,协调节点向客户端报告成功。