写点什么

一起学 Elasticsearch 系列 - 核心概念

作者:码农BookSea
  • 2023-11-06
    浙江
  • 本文字数:5481 字

    阅读完需:约 18 分钟

一起学Elasticsearch系列-核心概念

本文已收录至 Github,推荐阅读 👉 Java随想录

微信公众号:Java随想录


打算开个新的坑,创作关于 Elasticsearch 的系列文章


首先,让我们简单的了解一下 Elasticsearch:


Elasticsearch 是一个开源的搜索和分析引擎,支持近实时的大数据存储、搜索和分析。它基于 Apache Lucene 项目,提供全文搜索及能力强大的分布式多用户搜索引擎,同时配备 RESTful web 接口。它不仅能执行复杂查询,还能高效处理复杂的数据分析。


由于其出色的大数据处理能力,Elasticsearch 被广泛应用于需要快速搜索和分析大量结构化和非结构化数据的业务场景。


众多公司都广泛使用 Elasticsearch,而我们学习它,是因为它是当前最流行的搜索和数据分析解决方案之一。


这是该系列的首篇文章,本章将介绍 Elasticsearch 的基本概念和相关术语,以帮助您初步理解并熟悉 Elasticsearch。


注:所用的 Elasticsearch 版本为 7.4。

节点

ElasticSearch 是一种分布式搜索和分析引擎,它的核心是 Lucene。 ES 具有分布式特性,意味着它可以在很多不同的服务器上运行,这些服务器被称为 "节点"。


  • 每个 Elasticsearch 节点实际上就是一个 Java 进程,就是一个 Elasticsearch 的实例。

  • 一个节点 ≠一台服务器,意味着一台服务器上可以启动多个 Elasticsearch 的实例。


集群节点角色可以在配置文件elasticsearch.yml中通过node.roles配置,如果配置了节点角色,那么该节点将只会执行配置的角色功能。


根据角色的不同,Elasticsearch 的节点可以分为以下几种类型:

master:候选节点

所谓 master 节点,就是在主节点 down 机的时候,可以参与选举,取而代之的节点。


举个例子:


主节点好比班长,在班长不在的时候(主节点 down 机了),要选举出一个临时班长(master 中选举)


master 节点不仅有选举权还有被选举权,每个 master 节点主要负责索引创建、索引删除、追踪节点信息和决定分片分配节点等。


配置方法:


node.roles: [ master ]
复制代码

data:数据节点

数据节点顾名思义就是存放数据的节点,数据节点负责存储文档数据和数据的 CRUD 操作


因此该节点是 CPU 和 IO 密集型,需要实时监控该节点的资源信息,以免过载。


数据节点又可分为:data_content,data_hot,data_warm,data_code。


  • data_content:数据内容节点,目录节点负责存储常量数据,且不随着时间的推移,改变数据的温层(hot、warm、cold)。且该节点的查询优先级是高于其它 IO 操作,所以该节点 search 和 aggregations 都会较快一些。

  • data_hot:热节点,保存热数据,经常会被访问,用于存储最近频繁搜索和修改的时序数据。

  • data_code:冷节点,保存冷数据,很少会被访问,当数据不再更新,那么可以将该数据移动到冷数据节点,冷数据节点用于存储只读,且访问频率较低的数据。该节点机器性能可以低一点。

  • data_warm:温节点,介于热节点和冷节点之间,当数据访问频率下降,可以将其移动到温节点,温节点用于存储修改较少,但仍然有查询的数据,查询的频率肯定比热点节点要少。


配置方法:


node.roles: [ data ]
复制代码

Ingest:预处理节点

Ingest 节点是 Elasticsearch 的一种特殊类型的节点,用于预处理文档。预处理可能包括执行各种转换和修改,例如增加新字段、改变已有字段的值、移除字段、更改字段的数据类型等。


在 Elasticsearch 中,此类预处理操作是由 Ingest Pipeline 来完成的。一个 Ingest Pipeline 是一系列的处理器(processor),每一个处理器完成特定的任务。你可以定义多个处理器,然后按照特定的顺序执行。


要配置 Elasticsearch 使其具有 Ingest 能力,需要在 elasticsearch.yml 文件中设置如下:


node.roles: [ ingest ]
复制代码


以上设置表示该节点将作为 Ingest 节点。


以下是创建 Ingest Pipeline 的简单示例:


PUT _ingest/pipeline/my_pipeline_id{  "description" : "my pipeline",  "processors" : [    {      "set" : {        "field": "new_field",        "value": "new_value"      }    },    {      "remove" : {        "field": "old_field"      }    }  ]}
复制代码


这个 pipeline 包含两个处理器,第一个处理器在文档中添加了一个新字段,并设置了它的值;第二个处理器删除了一个旧字段。


之后在索引文档时,可以使用这个 pipeline:


PUT /my_index/_doc/my_id?pipeline=my_pipeline_id{  "field1" : "value1",  "old_field" : "value2"}
复制代码


在这个例子中,被索引的文档将被 Ingest pipeline 提前处理,添加新字段并删除旧字段。

ml:机器学习节点

Elasticsearch 的机器学习(ML)节点用于运行各种机器学习作业,例如异常检测或数据帧分析。这些节点特性在 Elasticsearch 的集群设置中进行配置。


配置 elasticsearch.yml:打开每个节点的 'elasticsearch.yml' 文件,并添加或修改以下设置:


node.roles: [ ml ]xpack.ml.enabled: true
复制代码


这些设置会使节点成为一个机器学习节点。


注意:在生产环境中,你应确保你的机器学习节点有足够的内存和 CPU 来处理你的机器学习工作负载。如果你尝试运行一个过于复杂或者数据量过大的机器学习作业,可能会导致节点崩溃或者过载。

remote_ cluster_ client:远程候选节点

远程候选节点可以作为远程集群的客户端,其作用在于帮助在本地集群与远程集群之间进行通信。当你希望模拟跨集群搜索或者跨集群复制时,这个节点角色就会派上用场。


配置:


node.roles: [ remote_cluster_client ]
复制代码


然后,你需要在elasticsearch.yml中设置远程集群的信息:


cluster:  remote:    my_remote_cluster:      seeds: 127.0.0.1:9300
复制代码


在此示例中,“my_remote_cluster”是远程集群的别名,而“seeds”是远程集群中的种子节点的地址列表。你可以根据实际情况来更改这些值。


注意:在某些环境中,可能需要额外的网络配置才能确保节点之间的正常通信。

transform:转换节点

转换节点(Transform)是一种将 Elasticsearch 索引数据进行统计分析并产生新的索引的功能。它可以用来执行复杂的聚合查询,并将结果持久化到新的 Elasticsearch 索引中。这个过程可以定期运行,也可以根据需求随时启动或停止。


以下是创建一个 Transform 的基本步骤:


  1. 使用 Kibana 或者 Elasticsearch API 来创建一个 Transform。你需要指定源索引(source index),目标索引(destination index),以及 Transform 的配置。

  2. 在 Transform 的配置中,你需要指定聚合查询(aggregations)以及群组字段(group by fields)。这些配置决定了怎样对源索引进行统计分析并生成新的索引。


一个简单的 Transform 配置示例如下:


PUT _transform/my_transform{  "source": {    "index": ["my_source_index"]  },  "dest": {    "index": "my_dest_index"  },  "pivot": {    "group_by": {      "user_id": {        "terms": {          "field": "user_id"        }      }    },    "aggregations": {      "total_clicks": {        "sum": {          "field": "clicks"        }      }    }  },  "frequency": "1m",  "sync": {    "time": {      "field": "timestamp",      "delay": "60s"    }  }}
复制代码


在上面的示例中,Transform 是从 my_source_index 中的数据计算每个 user_id 的点击次数总和,并将结果保存到 my_dest_index 中。这个 Transform 每分钟运行一次,并且在处理含有 timestamp 字段的最新数据时会有 60 秒的延迟。


更多关于 Elasticsearch Transform 的详细信息,建议参考 Elasticsearch 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/transform-apis.html

voting_ only:仅投票节点

在 master 选举过程中,仅投票节点顾名思义就是只参与主节点选举过程,但不会被选为主节点。


"voting-only"节点主要用来解决"split brain"(脑裂)的问题


在某些情况下,可能会发生两个或更多节点都认为自己是主节点的情况,这就是所谓的脑裂。通过增加"voting-only"节点,可以增加主节点选举的“选票”,从而降低脑裂的风险。


要将一个节点配置为"voting-only"节点,需要在该节点的elasticsearch.yml配置文件中设置以下属性:


node.roles: [voting_only]
复制代码


保存并重启该节点后,它就会成为一个"voting-only"节点。

coordinating only:协调节点

协调节点主要负责根据集群状态路由分发搜索,不参与索引和搜索操作,不存储数据,只负责将请求路由到适当的节点(例如数据节点或主节点),并根据结果组织响应返回给客户端。


此外每个节点都自带协调节点功能,即便没有去专门配置,任何 Elasticsearch 节点默认都能成为协调节点

分片

分片的思想在很多分布式应用和海量数据处理的场景中都非常常见,通常来说,面对海量数据的存储,单个节点显得力不从心。


通俗解释,分片就是将数据拆分多份,放到不同的服务器节点


Elasticsearch 里的分片分为两种:


  • 主分片(Primary Shard):这是最初创建索引时所设定的分片。主要用于数据持久化,可以通过配置文件或者 API 进行设置。

  • 副本分片(Replica Shard):这是从主分片复制出来的分片,用于提高数据的可用性和查询性能。副本不会与其对应的主分片放在同一节点上,以防止单点故障。

主分片

ES 可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。


分片的数量只能在索引创建前指定,并且索引创建后不能更改


ES 的分片数量在索引创建时设定是因为 ES 将每个索引的数据分布在多个分片上以实现数据的水平扩展。这种分布是基于数据的哈希值进行的,这样可以保证数据的均匀分布。一旦索引被创建并且数据开始写入,这种数据的分布就已经确定下来了。


当客户端发起创建 document 的时候,ES 需要确定这个 document 放在该 index 的哪个 shard 上。这个过程就是数据路由


路由算法:shard = hash(routing) % number_of_primary_shards


这里的routing指的就是 document 的 id,如果number_of_primary_shards在查询的时候取余发生了变化,则无法获取到该数据。


并且如果在索引创建后改变分片的数量,就需要重新计算所有数据的哈希值并且在分片之间迁移数据。这不仅会消耗大量的计算和 IO 资源,而且在数据迁移过程中还可能会影响查询的准确性。因此,ES 设计决定在索引创建时就确定分片的数量,而且创建后不能更改。


然而,虽然原始分片的数量在创建后不能更改,但是你可以通过 reindex 操作将数据复制到一个新的索引中,这个新的索引可以有不同的分片数量。

副本分片

副本分片代表索引的副本,ES 可以设置多个索引的副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高 ES 的查询效率,ES 会自动对搜索请求进行负载均衡。


  • 每个主分片和其副本分片不能存在于同一个节点上,所以最低的可用配置是两个节点互为主备。

  • 副本分片是不能直接写入数据的,只能通过主分片做数据同步。


以下是如何在创建索引时配置主分片和副本分片的示例:


PUT /my_index{    "settings": {        "number_of_shards": 3,  # 主分片数量        "number_of_replicas": 2 # 副本分片数量    }}
复制代码


这个设置会创建一个名为my_index的新索引,它有 3 个主分片和 2 个副本。也就是说,总共有 9 个分片 (3 主 * (1 原始 + 2 副本))。


你也可以在索引创建后修改其副本分片数:


PUT /my_index/_settings{    "number_of_replicas": 1}
复制代码


这将my_index索引的副本数从 2 更改为 1。


请注意,虽然你可以在索引创建后更改副本分片的数量,但不能更改主分片的数量。因此,在创建索引时,需要仔细考虑主分片的数量。

集群状态

集群健康状态(Cluster Health)描述了集群的总体健康状况,分为 "Green"、"Yellow" 和 "Red"。


  • Green:主/副分片都已经分配好且可用,集群处于最健康的状态 100%可用。

  • Yellow:主分片可用,但是至少有一个副本是未分配的。这种情况下数据也是完整的,但是集群的高可用性会被弱化。

  • Red:至少有一个不可用的主分片。此时只是部分数据可以查询,已经影响到了整体的读写,需要重点关注。

健康值检查

在 Elasticsearch 中,你可以使用两种主要的 API 来检查集群的健康状况:_cat/health_cluster/health。虽然它们提供了相似的信息,但是它们的输出格式不同。


_cat/health:该 API 以简洁的表格式返回关于集群健康的信息。它易于阅读和理解。


示例:GET _cat/health?v


这将返回如下所示的输出:


epoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent1605102382 13:59:42  elasticsearch green           3         3     12  6    0    0        0             0                  -                100.0%
复制代码


  • _cluster/health:这个 API 以 JSON 格式返回关于集群健康的详细信息。它提供更丰富的数据,并因此更适合编程访问。


示例:GET _cluster/health


这将返回如下所示的输出:


{  "cluster_name" : "elasticsearch",  "status" : "yellow",  "timed_out" : false,  "number_of_nodes" : 1,  "number_of_data_nodes" : 1,  "active_primary_shards" : 12,  "active_shards" : 12,  "relocating_shards" : 0,  "initializing_shards" : 0,  "unassigned_shards" : 2,  "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": 85.7}
复制代码


索引和文档

ES 中索引可以类比为关系型数据库中的 Table,在 7.0 版本之前 index 由若干个 type 组成,type 实际上是文档的逻辑分类,而文档是 ES 存储的最小单元。文档(doc)可以类比为关系型数据库中的行,每个文档都有一个文档 id。


7.0 及之后弱化了 type 的概念,7.x 版本 index 只有一个 type:_doc

发布于: 刚刚阅读数: 7
用户头像

码农BookSea

关注

Java开发工程师 2021-12-26 加入

Java开发菜鸟工程师,写博客的初衷是为了沉淀我所学习,累积我所见闻,分享我所体验。希望和更多的人交流学习。

评论

发布
暂无评论
一起学Elasticsearch系列-核心概念_Java_码农BookSea_InfoQ写作社区