Elasticsearch之常用术语
阅读原文时间:2023年09月06日阅读:1

关系型数据库

表(Table)

行(Row)

列(Cloumn)

Schema

SQL

Elasticsearch

索引(Index)

文档(Document)

字段(Filed)

Mapping

DSL

ElasticSearch(简称 ES) 是面向文档的,文档是所有可搜索数据的最小单位

给大家举几个例子,让大家更形象地理解什么是文档:

  • 日志文件中日志项
  • 一本电影的具体信息、一张唱片的详细信息
  • MP3 播放器里的一首歌、一篇 PDF 文档中的具体内容
  • 一条客户数据、一条商品分类数据、一条订单数据

大家可以把文档理解为关系型数据库中的一条记录。

2.1 文档存储结构

在 ES 中文档会被序列化成 JSON 格式,保存在 ES 中,JSON 对象由字段组成,其中每个字段都有对应的字段类型(字符串/数组/布尔/日期/二进制/范围类型)。

JSON 每个字段都有自己的数据类型,ES 可以帮助你自动做做一个数据类型的推算,并且在 ES 中数据还支持数组和嵌套

2.2 元数据

每一个文档都有对应的元数据,用于标注文档的相关信息,我们来了解下元数据都有什么内容:

-- 获取一个文档
GET movies/_search
{
  "size":1
}

返回结果中 hits 字段内容:

 {
        "_index": "movies",
        "_id": "2",
        "_score": 1,
        "_source": {
          "title": "Jumanji",
          "@version": "1",
          "event": {
            "original": """2,Jumanji (1995),Adventure|Children|Fantasy"""
          },
          "log": {
            "file": {
              "path": "/Users/zhulizhong/Software/elasticsearch/logstash-8.9.1/bin/movies.csv"
            }
          },
          "id": "2",
          "genre": [
            "Adventure",
            "Children",
            "Fantasy"
          ],
          "year": 1995
        }
      }

字段含义:

_index         文档所属的索引
_id            文档的Id
_score        为相关性打分,是这个文档在这次查询中的算分,分数越高越匹配
_source     表示文档正文的原始JSON
@version    文档版本信息,用于解决版本冲突问题

3.1 索引的定义

索引简单来说就是相似结构文档的集合,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称,一个索引可以包含很多文档,一个索引就代表了一类类似的或者相同的文档,比如说建立一个商品索引,里面可能就存放了所有的商品数据,也就是所有的商品文档。每一个索引都有自己的 Mapping 定义文件,用来去描述去包含文档字段的类型,分片(Shard)体现的是物理空间的概念,索引中的数据分散在分片上

3.2 索引结构

{
    "{indexName}": {// 索引名称
        "aliases": {},// 索引别名
        "mappings": {},// 索引结构定义
        "settings": { // 索引设置
        }
    }
}

在一个索引当中,可以去为它设置 aliases、Mapping 和 Setting,aliases 定义索引的别名, Mapping 定义的是索引当中所有文档字段的类型结构,Setting 主要是指定要用多少的分片以及数据是怎么样进行分布的。

3.3 索引含义区分

索引(名词):索引是一类文档的集合
索引(动词):保存一个文档到 ES 的过程
倒排索引:倒排索引是 ES 中一个重要的数据结构,类似于传统数据库的 B 树索引或者是倒排索引

每个索引里都可以有一个或多个 Type,Type 是索引中的一个逻辑数据分类,一个 Type 下的文档,都有相同的字段(Field),比如博客系统,有一个索引,可以定义用户数据 Type,博客数据 Type,评论数据 Type 等。

在 7.0 之前,每一个索引是可以设置多个 Types 的,每个 Type 会拥有相同结构的文档,但是在 6.0 开始,Type 已经被废除,在 7.0 开始,一个索引只能创建一个 Type,也就是 _doc

ES 集群其实是一个分布式系统,要满足高可用性,高可用就是当集群中有节点服务停止响应的时候,整个服务还能正常工作,也就是服务可用性;或者说整个集群中有部分节点丢失的情况下,不会有数据丢失,即数据可用性

当用户的请求量越来越高,数据的增长越来越多的时候,系统需要把数据分散到其他节点上,最后来实现水平扩展。当集群中有节点出现问题的时候,整个集群的服务也不会受到影响。

5.1 集群区分

ES 的分布架构当中,不同的集群是通过不同的名字来区分的,默认的名字为 elasticsearch,可以在配置文件中进行修改,或者在命令行中使用 -E cluster.name={name} 进行设定,一个集群中可以有一个或者多个节点。

5.2 集群健康状态

集群状态通过 绿 来标识健康程度:

  • 绿色(Green) - 一切都很好(集群功能齐全)。
  • 黄色(Yellow) - 所有数据均可用,但尚未分配一些副本。
  • 红色(Red) - 某些数据由于某种原因不可用(例如,当服务器的磁盘容量超过 85% 时,去创建了一个新的索引)。

可以在 Kibana 控制台通过 GET /_cluster/health 命令获取集群状态信息:

{
  "cluster_name": "docker-cluster",
  "status": "yellow",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 47,
  "active_shards": 47,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 26,
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 64.38356164383562
}

节点其实就是一个 ES 实例,本质上是一个 Java 进程,一台机器上可以运行多个 ES 进程,但是生产环境一般建议一台机器上只运行一个 ES 实例

每一个节点都有自己的名字,节点名称很重要(在执行运维管理操作的时候),可以通过配置文件进行配置,或者启动的时候 -E node.name=node1 指定。每一个节点在启动之后,会分配一个 UID,保存在 data 目录下。

默认节点会去加入一个名称为 elasticsearch 的集群,如果直接启动很多节点,那么它们会自动组成一个 elasticsearch 集群,当然一个节点也可以组成一个 elasticsearch 集群。

6.1 候选主节点(Master-eligible Node) & 主节点(Master Node)

每一个节点启动后,默认就是一个 Master-eligible 节点,可以通过在配置文件中设置 node.master: false 禁止,Master-eligible 节点可以参加选主流程,成为 Master 节点。当第一个节点启动时候,它会将自己选举成 Master 节点。

每个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息,如果是任意节点都能修改信息就会导致数据的不一致性。

集群状态(Cluster State),维护一个集群中必要的信息,主要包括如下信息:

  • 所有的节点信息
  • 所有的索引和其相关的 Mapping 与 Setting 信息
  • 分片的路由信息

6.2 数据节点(data Node) 协调节点(Coordinating Node)

顾名思义,可以保存数据的节点叫作 Data Node,负责保存分片上存储的所有数据,当集群无法保存现有数据的时候,可以通过增加数据节点来解决存储上的问题,在数据扩展上有至关重要的作用。

Coordinating Node 负责接收 Client 的请求,将请求分发到合适的节点,最终把结果汇集到一起返回给客户端,每个节点默认都起到了 Coordinating Node 的职责。

还有其他的节点类型,大家可以了解下:

6.3 其他节点类型

  • 冷热节点(Hot & Warm Node) :热节点(Hot Node)就是配置高的节点,可以有更好的磁盘吞吐量和更好的 CPU,那冷节点(Warm Node)存储一些比较久的节点,这些节点的机器配置会比较低。不同硬件配置的 Data Node,用来实现 Hot & Warm 架构,降低集群部署的成本。
  • 机器学习节点(Machine Learning Node):负责跑机器学习的工作,用来做异常检测。
  • 部落节点(Tribe Node):连接到不同的 ES 集群,并且支持将这些集群当成一个单独的集群处理。
  • 预处理节点(Ingest Node):预处理操作允许在索引文档之前,即写入数据之前,通过事先定义好的一系列的 processors(处理器)和 pipeline(管道),对数据进行某种转换、富化。

每个节点在启动的时候会通过读取 elasticsearch.yml 配置文件决定自己承担什么样的角色,那么让我们看下配置节点类型吧!

6.4配置节点类型

开发环境中一个节点可以承担多种角色。

生产环境中,应该设置单一的角色的节点(dedicated node)。

节点类型

配置参数

默认值

master-eliglble

node.master

true

data

node.data

true

ingest

node.ingest

true

coordinating only

每个节点默认都是 coordinating 节点,设置其他类型全部为 false

Machine learning

node.ml

true(需enable x-pack)

由于单台机器无法存储大量数据,ES 可以将一个索引中的数据切分为多个分片(Shard),分布在多台服务器上存储。有了分片就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。

一个 ES 索引包含很多分片,一个分片是一个 Lucene 的索引,它本身就是一个完整的搜索引擎,可以独立执行建立索引和搜索任务。Lucene 索引又由很多分段组成,每个分段都是一个倒排索引。 ES 每次 refresh 都会生成一个新的分段,其中包含若干文档的数据。在每个分段内部,文档的不同字段被单独建立索引。每个字段的值由若干词(Term)组成,Term 是原文本内容经过分词器处理和语言处理后的最终结果(例如,去除标点符号和转换为词根)。

7.1 分片类型

分片分为两类,一类为主分片(Primary Shard),另一类为副本分片(Replica Shard)

主分片主要用以解决水平扩展的问题,通过主分片,就可以将数据分布到集群上的所有节点上,一个主分片就是一个运行的 Lucene 实例,当我们在创建 ES 索引的时候,可以指定分片数,但是主分片数在索引创建时指定,后续不允许修改,除非使用 Reindex 进行修改

副本分片用以解决数据高可用的问题,也就是说集群中有节点出现硬件故障的时候,通过副本的方式,也可以保证数据不会产生真正的丢失,因为副本分片是主分片的拷贝,在索引中副本分片数可以动态调整,通过增加副本数,可以在一定程度上提高服务查询的性能(读取的吞吐)。

副本是乘法,越多越浪费,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。

PUT /blogs
{
    "settings" :{
        "number_of_shards" : 3,
        "number_of_repicas" : 1
    }
}

上面是 blogs 索引的定义,其中 settings 中的 number_of_shards 表示主分片数为 3,number_of_repicas 表示副本只有 1 份。

7.2 分片的设定

分片的设定在生产环境中是十分重要的,很多时候需要提前做好容量规划,因为主分片在索引创建的时候需要预先设定的,并且在事后无法修改,在前面的例子中,一个索引被分成了 3 个主分片,这个集群即便增加再多节点,索引也只能分散在 3 个节点上。

分片设置过大的时候,也会带来副作用,一方面来说会影响搜索结果的打分,影响统计结果的准确性,另外,单个节点上过多的分片,也会导致资源浪费,同时也会影响性能。从 7.0 版本开始,ES 的默认主分片数设置从 5 改为了 1,从这个方面也可以解决 over-sharding 的问题。

目前与 elasticsearch 交互主要有两种方式:Client API 和 RESTful API。

8.1 Client API

Elasticsearch 为以下语言提供了官方客户端 --Groovy、JavaScript、.NET、 PHP、 Perl、 Python 和 Ruby--还有很多社区提供的客户端和插件,所有这些都可以在 Elasticsearch Clients 中找到

8.2 REST API

所有其他语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信,你可以用你最喜爱的 web 客户端访问 Elasticsearch ,甚至可以使用 curl 命令来和 Elasticsearch 交互。