这种结构由文档中所有不重复词的列表构成,对于其中每个词都有一个文档列表与之关联。这种由属性值来确定记录的位置的结构就是倒排索引。带有倒排索引的文件我们称为倒排文件。
我们将上面的内容转换为图的形式来说明倒排索引的结构信息,如下图所示,
其中主要有如下几个核心术语需要理解:
词条(Term):索引里面最小的存储和查询单元,对于英文来说是一个单词,对于中文来说一般指分词后的一个词。
词典(Term Dictionary):或字典,是词条Term的集合。搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。
倒排表(Post list):一个文档通常由多个词组成,倒排表记录的是某个词在哪些文档里出现过以及出现的位置。每条记录称为一个倒排项(Posting)。倒排表记录的不单是文档编号,还存储了词频等信息。
倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件,倒排文件是存储倒排索引的物理文件。
从上图我们可以了解到倒排索引主要由两个部分组成:词典和倒排文件。词典和倒排表是Lucene中很重要的两种数据结构,是实现快速检索的重要基石。词典和倒排文件是分两部分存储的,词典在内存中而倒排文件存储在磁盘上。
核心概念一些基础知识的铺垫之后我们正式进入今天的主角Elasticsearch的介绍, ES是使用Java编写的一种开源搜索引擎,它在内部使用Lucene做索引与搜索,通过对Lucene的封装,隐藏了Lucene的复杂性,取而代之的提供一套简单一致的 RESTful API。
然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:
一个分布式的实时文档存储,每个字段可以被索引与搜索。
一个分布式实时分析搜索引擎。
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。
官网对Elasticsearch的介绍是Elasticsearch 是一个分布式、可扩展、近实时的搜索与数据分析引擎。 我们通过一些核心概念来看下Elasticsearch 是如何做到分布式,可扩展和近实时搜索的。
集群(Cluster)ES的集群搭建很简单,不需要依赖第三方协调管理组件,自身内部就实现了集群的管理功能。ES集群由一个或多个Elasticsearch节点组成,每个节点配置相同的 cluster.name 即可加入集群,默认值为 “elasticsearch”。确保不同的环境中使用不同的集群名称,否则最终会导致节点加入错误的集群。
一个Elasticsearch服务启动实例就是一个节点(Node)。节点通过node.name来设置节点名称,如果不设置则在启动时给节点分配一个随机通用唯一标识符作为名称。
发现机制那么有一个问题,ES内部是如何通过一个相同的设置cluster.name 就能将不同的节点连接到同一个集群的?答案是Zen Discovery。
Zen Discovery是Elasticsearch的内置默认发现模块(发现模块的职责是发现集群中的节点以及选举master节点)。它提供单播和基于文件的发现,并且可以扩展为通过插件支持云环境和其他形式的发现。Zen Discovery 与其他模块集成,例如,节点之间的所有通信都使用Transport模块完成。节点使用发现机制通过Ping的方式查找其他节点。
Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。
如果集群的节点运行在不同的机器上,使用单播,你可以为 Elasticsearch 提供一些它应该去尝试连接的节点列表。 当一个节点联系到单播列表中的成员时,它就会得到整个集群所有节点的状态,然后它会联系 master 节点,并加入集群。
这意味着单播列表不需要包含集群中的所有节点, 它只是需要足够的节点,当一个新节点联系上其中一个并且说上话就可以了。如果你使用 master 候选节点作为单播列表,你只要列出三个就可以了。 这个配置在 elasticsearch.yml 文件中:
discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]节点启动后先 ping ,如果discovery.zen.ping.unicast.hosts 有设置,则 ping 设置中的 host ,否则尝试 ping localhost 的几个端口, Elasticsearch 支持同一个主机启动多个节点, Ping 的 response 会包含该节点的基本信息以及该节点认为的 master 节点。 选举开始,先从各节点认为的 master 中选,规则很简单,按照 id 的字典序排序,取第一个。 如果各节点都没有认为的 master ,则从所有节点中选择,规则同上。