几个重要的概念

集群

集群中的一个节点就是一个 Elasticsearch 进程,多个节点组成一个集群
一般每个节点都运行在不同的操作系统上,配置好集群相关参数后 Elasticsearch 会自动组成集群 ( 节点发现方式也可以配置 )
集群内部通过 Elasticsearch 的选主算法选出主节点,而集群外部则是可以通过任何节点进行操作,无主从节点之分 ( 对外表现对等/去中心化,有利于客户端编程,例如故障重连 )

索引 _index

「 索引 」 有两个意思:

  1. 作为动词,它指的是把一个文档 「 保存 」 到 Elasticsearch 中的过程,索引一个文档后,我们就可以使用 Elasticsearch 搜索到这个文档
  2. 作为名词,索引是ElasticSearch存放数据的地方,可以理解为关系型数据库中的一个数据库,它可以映射为多种类型,每种数据类型可以认为是一个表。事实上,我们的数据被存储和索引在分片(shards)中,索引只是一个把一个或多个分片分组在一起的逻辑空间,可以拥有 0 个或多个副本。然而,这只是一些内部细节——我们的程序完全不用关心分片。对于我们的程序而言,文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。

    类型 _type

    类型用于区分同一个索引下不同的数据类型,相当于关系型数据库中的表。在Elasticsearch中,我们使用相同类型(type)的文档表示相同的“事物”,因为他们的数据结构也是相同的。每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。

    文档

    文档是ElasticSearch中存储的实体,类比关系型数据库,每个文档相当于数据库表中的一行数据。 在Elasticsearch中,文档(document)这个术语有着特殊含义。它特指最顶层结构或者根对象(root object)序列化成的JSON数据(以唯一ID标识并存储于Elasticsearch中)。
    每个文档都是保存在索引中的,拥有一种类型_type和 _id;一个文档是一个 JSON 对象;
    原始的 JSON 文本在索引后将被保存在 _source 字段里,搜索完成后返回值中默认是包含该字段的

    字段

    文档由字段组成,相当于关系数据库中列的属性,不同的是ES的不同文档可以具有不同的字段集合。
    一个文档包含了若干字段,或称之为键值对
    字段的值可以是简单标量值,例如字符串、整型、日期,也可以是嵌套结构,例如数组或对象
    每个字段的映射都有一个字段类型 ( 不要和文档类型搞混了 ),它描述了这个字段可以保存的值类型,例如整型、字符串、对象
    映射还可以让我们定义一个字段的值如何进行分析
    为了方便理解,我们可以将 Elasticsearch 中的一些概念对应到我们熟悉的关系型数据库上
Elasticsearch 索引 类型 文档 字段
DB 列属性

文档元数据

一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是:

节点 说明
_index 文档存储的地方
_type 文档代表的对象的类
_id 文档的唯一标识

_index:索引
_type:类型
_id:id仅仅是一个字符串,它与_index_type组合时,就可以在Elasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义_id,也可以让Elasticsearch帮你自动生成。

索引创建原则

  1. 类似的数据放在一个索引,非类似的数据放不同索引:product index(包含了所有的商品),sales index(包含了所有的商品销售数据),inventory index(包含了所有库存相关的数据)。如果你把比如product,sales,human resource(employee),全都放在一个大的index里面,比如说company index,不合适的。
  2. index中包含了很多类似的document:类似是什么意思,其实指的就是说,这些document的fields很大一部分是相同的,你说你放了3个document,每个document的fields都完全不一样,这就不是类似了,就不太适合放到一个index里面去了。
  3. 索引名称必须是小写的,不能用下划线开头,不能包含逗号:product,website,blog

    分片

    Elasticsearch 是一个分布式系统,我们一开始就应该以集群的方式来使用它。
    Elasticsearch 在保存索引时会选择适合的 「 主分片 」 ( Primary Shard ),把索引保存到其中
    我们可以把分片理解为一块物理存储区域
    分片的分法是固定的,而且是安装时候就必须要决定好的 ( 默认是 5 ),后面就不能改变了
    既然有主分片,那肯定是有 「 从 」 分片的,但 Elasticsearch 里称之为 「 副本分片 」 ( Replica Shard )
    副本分片主要有两个作用:

  4. 高可用
    某分片节点挂了的话可走其他副本分片节点,节点恢复后上面的分片数据可通过其他节点恢复

  5. 负载均衡
    Elasticsearch 会自动根据负载情况控制搜索路由,副本分片可以将负载均摊

    范例

    我们举一个简单的例子来总结上面阐述的内容
    Elasticsearch 术语 - 图1
    该图是使用 Elasticsearch 的 RESTful 接口获取的,后面会介绍常用接口
    上图中:

  6. 3 个 Elasticsearch 节点 ( es-58/59/60 ) 组成一个集群

  7. 搭建集群时使用默认的主分片数 5,shard0 ~ shard4
  8. 该集群内有加入两个索引 index1、index2
  9. 这两个索引中分别 「 索引 」 ( 保存 ) 了两个文档
  10. index1 索引中这个文档被 Elasticsearch 自动保存到了分片 2 中,主分片在 es-58 节点,副本分片在 es-59 节点
  11. index2 索引中这个文档被 Elasticsearch 自动保存到了分片 2 中,主分片在 es-59 节点,副本分片在 es-58 节点

image.png

多租户

Elasticsearch 中的多租户简单的说就是通过多索引机制同时提供给多种业务使用,每种业务使用一个索引 ( 关于多租户的详细定义与用途,可以参考这里 )
前面我们提到过可以把索引理解为关系型数据库里的库,那多索引可以理解为一个数据库系统建立多个库给不同的业务使用
实际使用时,我们可以通过每个租户一个索引的方式将他们的数据进行隔离,并且每个索引是可以单独配置参数的 ( 可对特定租户进行调优 )
这在典型的多租户场景下非常有用:例如我们的一个多租户应用需要提供搜索支持,这时可以通过 Elasticsearch 根据租户建立索引,这样每个租户就可以在自己的索引下搜索相关内容了

RESTful

因为 RESTful,所以 Elasticsearch 接口非常清晰方便简单。
最关键的是 Elasticsearch 的 HTTP 接口不只是可以进行业务操作 ( 索引/搜索 ) ,还可以进行配置,甚至是关闭 Elasticsearch 集群
下面我们介绍几个很常用的接口

接口 说明
/_cat/nodes?v 查集群状态
/_cat/shards?v 查看分片状态
/$ 搜索
  1. v 是 verbose 的意思,当使用这个参数,那么返回结果则更具可读性 ( 有表头,有对齐 )
  2. _cat 是监测相关的 APIs。可以使用 /_cat?help 来获取所有接口
  3. ${index}${type} 分别是具体的某一索引某一类型,是分层次的

    Elasticsearch 术语

    接下里的教程为涉及到很多术语,这些术语可能比较难懂,不过没关系,你不懂也可以继续,当不懂某个术语的时候,回来这篇文章看看就知道了

    analysis 分析

    分析是将文本 ( text ) 转化为查询词 ( term ) 的过程
    比如这三种短语:FOO BAR,Foo-Bar,foo,bar 都有可能被分解成查询词 foo 与 bar
    可以使用不同的分析器,这些查询词实际上将被存储在索引中
    一次对 FoO:bAR 的全文查询 ( 不是查询词查询 ) 可能会被分析为为查询词 foo,bar,可以匹配上保存在索引中的查询词
    这就是分析处理过程(包含了索引与搜索),它使得 es 可以进行全文查询
    cluster ( 集群 )
    一个或多个拥有同一个集群名称的节点组成了一个集群
    每个集群都会自动选出一个主节点,如果该主节点故障,则集群会自动选出新的主节点来替换故障节点

    mapping ( 映射 )

    一个映射类似于关系型数据库中的表
    每个索引都存在一个映射,它定义了该索引中的每一种类型,以及索引相关的配置
    映射可以显示定义,或者在文档被索引时自动创建

    node ( 节点 )

    一个节点是集群中的一个 Elasticsearch 运行实例
    测试环境,多个节点可以同时启在同一个服务器上,生产环境一般是一个服务器上一个节点
    节点启动时将使用单播或者是组播来发现和自己配置的集群名称相同的集群,并尝试加入到该集群中

    shard ( 分片 )

    一个分片就是一个 Lucene 实例,它是 Elasticsearch 管理的底层 「 工作单元 」
    一个索引是逻辑上的一个命名空间,指向主分片和副本分片
    索引的主分片和副本分片数量必须明确指定好,在应用代码使用时只需要处理和索引的交互,不会涉及到和分片的交互
    Elasticsearch 会在集群中的所有节点上设置好分片,但节点失效或加入新节点时会自动将移动节点分片

    primary shard ( 主分片 )

    每个文档都会被保存在一个主分片上
    当我们索引一个文档时,它将在一个主分片上进行索引,然后才放到该主分片的各副本分片上
    默认情况下,一个索引有 5 个主分片
    我们可以指定更少或更多的主分片来伸缩索引可处理的文档数

    需要注意的是,一旦索引创建,就不能修改主分片个数

replica shard ( 副本分片 )

每个主分片可以拥有 0 个或多个副本分片,一个副本分片是主分片的一份拷贝
这样做有两个主要原因:

  1. 故障转移
    当主分片失效时,一个副本分片会被提升为主分片
  2. 提高性能
    获取与搜索请求可以被主分片或副本分片处理
    默认情况下,每个主分片都有一个副本分片,副本分片的数量可以动态调整
    在同一个节点上,副本分片和其主分片不会同时运行

    routing ( 路由 )

    当我们索引一个文档时,它将被保存在一个主分片上,分片的选择是通过路由值哈希得到的
    默认情况下,路由值使用文档的 id,如果该文档指定来了父文档,则路由值使用父文档 id
    这是为了确保子文档和父文档被保存在相同的分片上
    该值可以在索引时指定,也可以通过映射路由字段来指定

    source field ( 源字段 )

    默认情况下,在获取和搜索请求返回值中的 _source 字段保存了源 JSON 文本
    这使得我们可以直接在返回结果中访问源数据,而不需要根据 id 再发一次检索请求

    索引的 JSON 字符串将完整返回,无论是否是一个合法的 JSON 该字段的内容也不会描述数据如何被索引

term ( 查询词 )

一个查询词是一个被 Elasticsearch 索引的确切值
查询词 foo,Foo,FOO 是不同的
查询词可以使用查询词查询接口进行获取

text ( 文本 )

文本 ( 或称之为全文 ) 是普通的、非结构化的文本,例如一句话。
默认情况下,文本将被分解为查询词,查询词将被保存在索引中
为能够进行全文搜索,文本字段在索引时将被分解为查询词,查询关键字在搜索时也将被分解为查询词,通过对比查询词是否相同而完成全文搜索

type ( 类型 )

一种类似于关系型数据库中的一张表的类型
每种类型都有若干字段,用于指定给该类型文档
映射定义了该文档中的每个字段如何进行分析
Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多 个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。