ELK 之 Elasticsearch 查询介绍

Elasticsearch(ES)是一个基于 Apache Lucene(TM) 构建的开源分布式全文搜索引擎.它通过 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单.它作为分布式文档数据库,其中存储的每个字段及值均可被索引.

Elasticsearch 有如下特性:

  • 分布式的数据存储工具,实时分析搜索引擎.存储在其中的每个字段都被索引并可被搜索
  • 提供 RESTful 风格的 API 接口,简单易用
  • 易扩展.它可以扩展到上百台服务器,处理 PB 级结构化或非结构化数据

概念介绍

基本概念

  • index 索引

索引是多个具有相似特性的文档集合.ES 中可以创建任意数量的索引,但索引名必须使用小写字母

  • type 类型

类型是索引内部的逻辑分区.一般来说,类型定义为具有公共字段集的文档

  • document 文档

文档是可以被搜索的基本单位,它基于 JSON 格式表示,一般包含多个字段.

可以简单的将 ES 中基本概念与关系型数据库概念对应起来:

Elasticsearch 关系型数据库
index 索引 database 数据库
type 类型 table 表
document 文档 row 数据行
field 字段 column 数据列
mapping 映射 data_type 数据类型

集群概念

  • node 节点

节点是运行 Elasticsearch 实例的主机.它用于存储数据,参与集群索引及搜索操作.同一个集群内的节点名必须唯一,通过 node.name 进行设置

  • cluster 集群

集群是一个或多个 Elasticsearch 节点的集合.这些节点共同存储整个数据,并在所有节点上提供联合索引和搜索功能.一个节点只能加入一个集群

  • shard 分片

Elasticsearch 将索引切为多个小的片段,每一个片段都是一个分片.分片都是独立且完整的小索引,提供分布式读写负载均衡功能

用户可以通过 index.number_of_shards 设定分片数量,设定后不可更改.默认为 5

  • replica 副本

ES 将分片保存为多个副本,提供冗余高可用.副本之间为主从机制,可能存在主从数据不同步的问题.主读写,从只读

用户可以通过 index.number_of_replicas 设置副本数量,设置后可进行更改

ES Cluster 工作原理

集群启动

  1. ES 启动时,通过多播(默认)或单播的方式在 tcp/9300 查找同一集群中的其它节点,并与之建立通信
  2. 集群中选举出一个主节点负责管理整个集群状态,以及在集群范围内决定各个分片的分配方式.站在用户角度而言,每个节点均可接收并响应用户的各类请求
  3. 假如集群中某一节点故障,主节点会读取集群状态信息,并启动修复过程,进入修复模式.此时,集群处于 yellow 状态,所有的副本分片处于为未分配状态.
  4. 在此时模式中,主节点会检查所有可用分片,并确定各主分片及其对应的副本数量是否满足配额.假如故障节点包含某一主分片,则需要从各个副本分片中选举出一个作为主分片.假如故障节点包含某一副本分片,则集群会启动处理过程,为之重新建立副本,直到满足配额.

集群状态: green(健康), yellow(亚健康,修复模式), red(故障)

分布式搜索

在搜索过程中,由于不知道哪个分片中的文档会匹配到搜索条件,所以一个搜索请求不得不通过查询每一个我们感兴趣的索引的分片副本来查看是否含有任何匹配的文档.该过程称为查询.

但是,找到所有匹配的文档只完成了这件事的一半.在搜索 _search API 返回结果前,来自多个分片的结果必须被组合放到一个有序列表中.该过程称为取回

  • 查询阶段

当搜索请求被发送到 ES 节点,这个节点就变成了协调节点.这个节点的工作是向指定索引的所有分片广播搜索请求并且把它们的响应整合成一个全局的有序结果集.

在初始化查询阶段,查询请求会向索引中的每个分片副本广播,每个分片在本地执行搜索并建立匹配文档的优先队列.一个优先队列只是一个存有前 n 个匹配文档的有序列表.这个优先队列的大小由分页参数 fromsize 决定,一般为 from + size

  • 取回阶段

协调节点辨别出哪个文档需要取回,并且向相关分片发出 GET 请求.每个分片加载文档并且根据需要处理它们,然后再将文档返回协调节点.等到所有符合条件的文档都被取回,协调节点会将结果返回给客户端.

Document APIs

文档由元数据和内容组成.一般来说,元数据包括文档的 _index, _type, _id, _version 等字段组成, 其中 _index, _type, _id 可用于唯一确定一个文档._version 用于标识该文档的版本信息.文档内容由 _source 字段组成,其中包含我们存储文档时提交的 JSON 信息.

通用请求路径参数

以下是通用的路径请求参数,在不同 API 中可能有不同的选填或必填需求.

  • index: 指定索引名称.必填参数
  • _id: 文档的唯一标识.PUT,GET,HEAD,DELETE 请求必填.POST 请求可以省略,会自动生成.

Index API

将 JSON 文档添加到指定索引并使其可搜索,如果文档已存在,更新文档并增加其版本

1
2
3
4
PUT /<index>/_doc/<_id>
POST /<index>/_doc/
PUT /<index>/_create/<_id>
POST /<index>/_create/<_id>

Get API

使用 Get 请求从特定索引中检索文档或字段,使用 HEAD 请求验证文档是否存在. 使用 _source 对文档内容操作.

1
2
3
4
GET <index>/_doc/<_id>
HEAD <index>/_doc/<_id>
GET <index>/_source/<_id>
HEAD <index>/_source/<_id>

请求参数

  • routing: 只在指定分片中进行搜索.我们可以在建立索引时提供一个自定义的 routing 参数来保证所有相关的文档(如属于单个用户的文档)被存放在一个单独的分片中.在搜索时,我们可以指定一个或多个 routing 值来限制只搜索指定的分片.
  • _source: 是否返回 _source 文档内容,默认为 true
  • _source_excludes: 从返回的 _source 字段中排除的字段列表
  • _source_includes: 从 _source 字段提取并返回的字段列表

Delete API

从指定的索引中删除指定的文档

1
DELETE /<index>/_doc/<_id>

Delete by query API

删除与指定查询匹配的文档,<index> 为选填参数,且支持使用逗号指定多个,默认为 _all

1
POST /<index>/_delete_by_query

请求参数

  • from: 文档的开始位置.默认为 0
  • max_docs: 要处理的最大文档数,默认为所有
  • q: 使用 Lucene 查询语法查询
  • routing: 只在指定分片中进行搜索
  • scroll_size: 操作滚动的大小,默认 100
  • sort: 排序,以逗号分隔的 <field>:<direction> 列表
  • _source: 是否返回 _source 文档内容,默认为 true
  • _source_excludes: 从返回的 _source 字段中排除的字段列表
  • _source_includes: 从 _source 字段提取并返回的字段列表

请求体

  • query: Query DSL 格式的请求,用于筛选文档

Update API

使用指定内容或脚本更新指定文档

1
POST /<index>/_update/<_id>
Buy me a cup of coffee.