读书笔记《elasticsearch-server-third-edition》管理您的群集
在上一章中,我们重点介绍了 Elasticsearch 节点和集群配置。我们首先讨论了节点发现过程、它是什么以及如何配置它。我们已经讨论了网关和恢复模块,并对其进行了调整以满足我们的需求。我们使用模板和动态模板轻松管理数据结构,并学习了如何安装插件来扩展 Elasticsearch 的功能。最后,我们了解了 Elasticsearch 的缓存以及如何使用专用 API 更新索引和集群设置。在本章结束时,您将学习以下主题:
在 Elasticsearch 中备份您的索引
监控您的集群
控制分片和重新平衡副本
控制分片和分配副本
使用 CAT API 了解集群状态
热身
别名
一个好的软件是一种可以管理异常情况的软件,例如硬件故障或人为错误。即使由几台服务器组成的集群对硬件问题的依赖程度较低,但仍然可能发生坏事。例如,假设您需要恢复索引。一种可能的解决方案是从 SQL 数据库等主数据存储重新索引所有数据。但是如果花费的时间太长,或者更糟糕的是,唯一的数据存储是 Elasticsearch,你会怎么做?在 Elasticsearch 1.0 之前,创建索引备份并不容易。该过程包括停止索引、将数据刷新到磁盘、关闭集群,最后将数据复制到备份设备。
幸运的是,现在我们可以拍摄快照,本节将指导您并展示此功能的工作原理。
快照保留了从快照创建开始时与集群相关的所有数据,其中包括有关集群状态和索引的信息。在我们创建快照之前,至少是第一个,必须创建一个快照存储库。每个存储库都通过其名称识别,并应定义以下方面:
name:存储库的唯一名称;我们稍后会需要它。type:存储库的类型。可能的值是fs(共享文件系统上的存储库)和url(可通过 URL 获得的只读存储库)settings:需要的附加信息取决于repository类型
现在,让我们创建一个文件系统存储库。在此之前,我们必须确保我们的备份目录满足两个要求。第一个与安全有关。每个存储库都必须放置在 Elasticsearch 配置文件中定义为 path.repo 的路径中。例如,我们的 elasticsearch.yml 包含类似于以下的一行:
第二个要求是集群中的每个节点都应该能够访问我们为存储库设置的目录。
所以现在,让我们通过运行以下命令来创建一个新的文件系统存储库:
上述命令创建了一个名为 backup 的存储库,它将备份文件存储在 location 属性给定的目录中。 Elasticsearch 使用以下信息进行响应:
同时,本地文件系统上的 es_backup_folder 被创建——还没有任何内容。
正如我们所说,第二种存储库类型是 url。它需要一个 url 参数而不是 location,它指向存储库所在的地址,例如 HTTP 地址。如上例中的,地址应该定义在repositories.url.allowed_urls参数中弹性搜索配置。该参数允许在地址中使用通配符。
您还可以 使用 附加功能将快照存储在 Amazon S3、HDFS 或 Azure 中插件可用。要了解这些,请访问以下页面:
现在我们有了第一个存储库,我们可以使用以下命令查看它的定义:
我们还可以通过运行如下命令来检查所有存储库:
或者简单地说,我们可以使用这个:
如果要删除快照存储库,标准的 DELETE 命令可以帮助:
默认情况下,Elasticsearch 会获取所有索引 和集群设置(临时索引除外) ) 创建快照时。您可以创建任意数量的快照,每个快照都将保存从创建快照时可用的信息。快照以智能方式创建;只复制新信息。这意味着 Elasticsearch 知道哪些段已经存储在存储库中,而不必再次保存它们。
要创建新快照,我们需要选择一个唯一的名称并使用以下命令:
上述命令定义了一个名为 bckp1 的新快照(您只能拥有一个具有给定名称的快照;Elasticsearch 将检查其唯一性),数据存储在 以前定义的备份存储库。 命令返回立即响应,如下所示:
前面的响应意味着快照过程已经开始并在后台继续。如果您希望仅在创建实际快照时返回响应,您可以添加 wait_for_completion=true 参数,如下例所示:
对上述命令的响应显示了已创建快照的状态:
如您所见,Elasticsearch 提供有关快照过程所用时间、其状态和受影响的索引的信息。
indices:我们要对其进行快照的索引的名称。ignore_unavailable:当设置为false(默认)时,如果使用 indices 参数列出的任何索引,Elasticsearch 将返回错误不见了。当设置为 true 时,Elasticsearch 将在备份期间忽略丢失的索引。include_global_state:当设置为true(默认)时,集群状态也会写入快照(除了瞬态设置)。partial:快照操作是否成功取决于所有分片的可用性。如果任何分片不可用,快照操作将失败。将 partial 设置为 true 会导致 Elasticsearch 仅保存可用的分片并忽略丢失的分片。
使用附加参数的示例如下所示:
现在我们已经完成了快照,我们还将学习如何从给定的快照中恢复数据。正如我们之前所说,快照可以通过其名称来寻址。我们可以使用以下命令列出所有快照:
Elasticsearch 对上述命令返回的响应显示了所有可用备份的列表。每个列表项都类似于以下内容:
我们之前创建的存储库称为 backup。要从我们的快照存储库恢复名为 bckp1 的快照,请运行以下命令:
在执行此命令期间,Elasticsearch 获取快照中定义的索引并使用快照中的数据创建它们。但是,如果索引已存在且未关闭,则该命令将失败。在这种情况下,您可能会发现只恢复某些索引很方便,例如:
前面的命令仅恢复以字母 c 开头的索引。其他可用的 参数如下:
ignore_unavailable:此参数设置为false(默认行为)时,如果任何预期指数不可用。include_global_state:该参数设置为true时会导致Elasticsearch恢复快照中包含的全局状态,这也是默认行为。rename_pattern:此参数允许在还原操作期间重命名索引。因此,恢复的索引将具有不同的名称。此参数的值是定义源索引名称的正则表达式。如果模式与索引的名称匹配,则会发生名称替换。在该模式中,您应该使用由rename_replacement参数中使用的括号限制的组。rename_replacement:此参数与rename_pattern一起定义目标索引名称。使用美元符号和数字,您可以从rename_pattern中调用适当的组。
例如,由于 rename_pattern=products_(.*),只会恢复名称以 products_ 开头的索引。索引名称的其余部分将在替换期间使用。 rename_pattern=products_(.*) 与 rename_replacement=items_$1 一起导致 products_cars
索引要恢复为名为 items_cars 的索引。
在处理集群并确保其处于健康状态时,监控 至关重要。它允许管理员和开发人员检测可能的问题并在它们发生之前加以预防,或者在它们开始出现时立即采取行动。在最坏的情况下,监控允许我们对应用程序发生的事情进行事后分析——在这种情况下,我们的 Elasticsearch 集群和每个节点。
Elasticsearch 提供了非常详细的信息,使我们能够检查和监控我们的节点或整个集群。这包括有关服务器、节点、索引和分片的统计信息和信息。当然,我们也可以获取整个集群状态的信息。在我们深入了解上述 API 的详细信息之前,请记住 API 很复杂,我们只描述了基础知识。我们将尝试向您展示从哪里开始,以便您在需要非常详细的信息时知道要查找的内容。
其中一个最基本的 API 是集群 健康 API,它允许我们使用单个 HTTP 命令获取有关整个集群状态的信息。例如,让我们运行以下命令:
Elasticsearch 为上述命令返回的示例响应如下所示:
最重要的信息是关于集群的状态。在我们的示例中,我们看到集群处于黄色状态。这意味着所有主分片都已正确分配,但副本没有(因为集群中只有一个节点,但现在没关系)。
当然,除了集群名称和状态,我们还可以看到请求是如何超时的,有多少节点,有多少数据节点,主分片,初始化分片,未分配的分片等等。
让我们在这里停下来谈谈集群,以及集群作为一个整体何时全面运行。当 Elasticsearch 能够根据配置分配所有分片和副本时,集群就可以完全运行。这是集群处于绿色状态的时候。黄色状态表示我们已准备好处理请求,因为主分片已分配,但部分(或全部)副本未分配。最后一个状态,红色状态,表示至少有一个主分片没有分配,因此,集群还没有准备好。这意味着查询可能会返回错误或不完整的结果。
也可以执行上述命令来检查某些索引的健康状态。例如,如果我们想检查 library 和 map 索引的健康状况,我们将运行以下命令:
Elasticsearch 允许我们指定一个特殊的 level 参数,它可以取 簇(默认)、索引或分片。这使我们能够控制健康 API 返回的信息的详细信息。我们已经看到了默认行为。当将 level 参数设置为 indices 时,除了集群信息外,我们还将获得每个索引的健康状况。将上述参数设置为 shards 告诉 Elasticsearch 除了返回 之外的每个分片信息。在示例中。
在除了level参数外,我们还有一些额外的参数可以控制健康的行为API。
提到的第一个参数是 timeout 并且允许我们控制最多多长时间,当使用以下参数之一时命令执行将等待: wait_for_status、wait_for_nodes、wait_for_relocating_shards 和 wait_for_active_shards >。默认情况下,它设置为 30s,这意味着 health 命令将最多等待 30 秒,然后返回响应。
wait_for_status 参数允许我们告诉 Elasticsearch 集群应该处于哪种健康状态才能返回命令。它可以取 green、yellow 和 red 的值。例如,当设置为 green 时,健康 API 调用将返回结果,直到达到绿色状态或超时。
wait_for_nodes 参数允许我们设置可用于返回健康命令响应的所需节点数(或直到达到定义的超时)。它可以设置为像 3 这样的整数或像 >=3 这样的简单等式(表示大于或等于三个节点)或 <=3(表示小于或等于三个节点)。
wait_for_active_shards 参数意味着 Elasticsearch 将在返回响应之前等待指定数量的活动分片出现。
最后一个参数是wait_for_relocating_shard,默认不指定。它允许我们告诉 Elasticsearch 它应该等待多少重定位分片(或直到达到超时)。将此参数设置为 0 意味着 Elasticsearch 应该等待所有重新定位的分片。
带有一些提到的参数的 health 命令的示例用法如下:
Elasticsearch 索引 是我们的 数据所在的地方,它是大多数部署。通过使用 _stats 端点提供的索引统计 API,我们可以获得有关集群内索引的大量信息。当然,与 Elasticsearch 中的大多数 API 一样,我们可以发送一个命令来获取有关所有索引的信息(使用纯 _stats 端点),关于一个特定索引(例如 library/_stats) 或同时使用多个索引(例如 library,map/_stats)。例如,要检查我们在书中使用的 map 和 library 索引的统计信息,我们可以运行以下命令命令:
对上述命令的响应有 700 多行,所以我们只描述它的结构,省略响应本身。除了响应状态和响应时间的信息,我们可以看到三个 名为 primaries、total 的对象(在 _all 对象中)和 <代码类="literal">索引。 indices 对象包含有关 library 和 map 索引的信息。 primaries 对象包含有关分配给当前节点的主分片的信息,而 total 对象包含有关所有分片的信息,包括复制品。所有这些对象都可以包含描述特定统计信息的对象,例如:docs、store、indexing, get, 搜索, 合并, < code class="literal">refresh, flush, warmer, query_cache , fielddata, 渗透, 完成, segments, translog, suggest, request_cache
和 recovery。
我们可以通过使用前面提到的统计信息的名称提供我们感兴趣的数据类型来限制从索引统计 API 获得的信息量。例如,如果我们想获取有关索引和搜索的信息,我们可以运行以下命令:
让我们讨论存储在这些对象中的信息。
响应的 docs 部分 显示有关索引文档的信息。例如,它可能如下所示:
主要信息是count,表示所描述索引中的文档数。当我们从索引中删除文档时,Elasticsearch 不会立即删除这些文档,只会将它们标记为已删除。文档在段合并过程中被物理删除。标记为已删除的文档数由 deleted 属性表示,在合并后应立即为 0。
下一个 统计数据,即 store 统计数据,提供有关存储的信息。例如,这样的部分可能如下所示:
主要信息是关于索引(或索引)的大小。我们还可以查看限制统计信息。当系统出现 I/O 性能问题并在段合并期间配置了内部操作的限制时,此信息很有用。
响应的 indexing、get 和 search 部分提供有关数据操作 索引和删除操作,使用实时get 和搜索。让我们看一下 Elasticsearch 返回的以下示例:
如您所见,所有这些统计数据都具有相似的结构。我们可以读取各种请求类型所花费的总时间(以毫秒为单位)、请求的数量(总时间 允许我们计算平均时间单个查询)。在get请求的情况下,有价值的信息是 有多少次获取不成功(缺少文档);索引请求包含有关限制的信息,搜索包含有关滚动的信息。
在 中,除了前面描述的部分,Elasticsearch 还提供了以下信息:
merges:此部分包含有关 Lucene 段合并的信息refresh:此部分包含有关刷新操作的信息flush:此部分包含有关刷新的信息warmer:此部分包含有关 warmers 及其执行时间的信息query_cache:此查询缓存统计信息fielddata:该字段数据缓存统计信息percolate:此部分包含有关 percolator 使用的信息completion:此部分包含有关完成提示器的信息segments:此部分包含有关 Lucene 段的信息translog:此部分包含有关事务日志计数和大小的信息suggest:此部分包含与建议者相关的统计信息request_cache:这包含分片请求缓存统计信息recovery:这包含分片恢复信息
节点信息 API 为我们提供了关于集群中节点的信息。要从此 API 获取信息,我们需要将请求发送到 _nodes REST 端点。从 Elasticsearch 检索节点相关信息的最简单命令如下:
此 API 可用于获取有关特定节点或单个节点的信息 使用以下:
Node name:如果我们想获取名为
Pulse的节点的信息,我们可以运行到以下 REST 端点的命令:_nodes/Pulse节点标识符:如果我们想获取标识符等于
ny4hftjNQtuKMyEvpUdQWg的节点的信息,我们可以向以下 REST 端点运行命令:_nodes/ny4hftjNQtuKMyEvpUdQWgIP地址:我们可以使用IP地址来获取节点信息。例如,如果我们想获取 IP 地址等于
192.168.1.103的节点的信息,我们可以向以下 REST 端点运行命令:_nodes/192.168.1.103来自 Elasticsearch 配置的参数:如果我们想通过
node.rack< 获取所有节点的信息/code> 属性设置为2,我们可以向以下 REST 端点运行命令:/_nodes/rack:2
此 API 还允许我们使用以下方式一次获取有关多个节点的信息:
模式,例如:
_nodes/192.168.1.*或_nodes/P*节点枚举,例如:
_nodes/Pulse,Slab模式和枚举,例如:
/_nodes/P*,S*
节点统计 API 类似于上一节中描述的节点信息 API。 的主要区别在于,之前的 API 提供了有关节点运行环境的信息,而我们目前讨论的 API 告诉我们发生了什么集群在其工作期间。要使用节点统计 API,您需要向 /_nodes/stats REST 端点发送命令。但是,与节点信息 API 类似,我们也可以检索特定节点的信息(例如:_nodes/Pulse/stats)。
从 Elasticsearch 检索节点相关信息的最简单命令如下:
默认情况下,Elasticsearch 返回所有可用的统计信息,但我们可以限制我们感兴趣的统计信息。可用的选项如下:
indices:有关索引的信息,包括大小、文档计数、索引相关统计信息、搜索和获取时间、缓存、段合并等os:可用磁盘空间、内存、swap使用等操作系统相关信息process:与 Elasticsearch 进程相关的内存、CPU 和文件处理程序使用情况jvm:Java虚拟机内存和垃圾收集器统计transport:传输模块发送和接收的数据信息http:关于http连接的信息fs:可用磁盘空间和I/O操作统计信息thread_pool:分配给各种操作的线程状态信息breakers:关于断路器的信息script:脚本引擎相关信息
Elasticsearch 提供的另一个 API 是集群状态API。顾名思义,它允许我们获取整个集群的信息(我们也可以通过在请求中添加 local=true 参数来限制返回的信息到本地节点) .用于获取此 API 返回的所有信息的基本命令如下所示:
我们还可以将提供的信息限制为逗号分隔形式的给定指标,在 REST 调用的 _cluster/state 部分之后指定。例如:
我们还可以将信息限制在给定的指标和索引中。例如,如果我们想获取 library 索引的元数据,我们可以运行以下命令:
允许使用以下指标:
version:返回关于集群状态版本的信息。master_node:这返回有关选举的主节点的信息。nodes:返回节点信息。routing_table:返回路由相关信息。metadata:返回元数据相关信息。在指定检索元数据指标时,我们还可以包含一个附加参数,例如index_templates=true,这将导致包含已定义的索引模板。blocks:返回响应的blocks部分。
集群统计 API 允许我们从集群范围的角度获取有关索引和节点的统计信息。要使用此 API,我们需要向 /_cluster/stats REST 端点运行 GET 请求,例如:
响应大小取决于集群中的分片、索引和节点的数量。它将 包括基本索引信息,例如分片、它们的状态、恢复信息、缓存信息和节点相关信息。
一个 API 可以帮助我们了解 Elasticsearch 正在做什么;它允许我们检查哪些任务正在等待执行。要检索此信息,我们需要向 /_cluster/pending_tasks REST 端点发送请求。在此响应中,我们将看到一组任务及其相关信息,例如任务优先级和排队时间。
recovery API 让我们了解集群中正在构建索引的分片的恢复状态(在 第 9 章的网关和恢复模块部分,Elasticsearch 集群详解)。
返回集群中所有分片恢复信息的最简单命令如下所示:
我们还可以获取有关特定索引恢复的信息,例如 library 索引,例如:
Elasticsearch 返回的响应按索引和分片划分。单个分片的响应可能如下所示:
在 之前的响应中,我们可以看到有关分片标识符、恢复阶段、分片是主分片还是副本分片的信息、时间戳恢复的开始和结束,以及恢复过程所用的总时间。我们可以看到源节点、目标节点,以及分片的物理统计信息,例如大小、文件数、事务日志相关的统计信息、索引验证时间等。
值得了解有关恢复阶段和类型的信息。当涉及到恢复的类型(响应中的 type 属性)时,我们可以预期以下内容:STORE, SNAPSHOT、REPLICA 和 RELOCATING 值。当涉及到恢复阶段(响应中的 stage 属性)时,我们可以预期诸如 INIT 之类的值(recovery尚未启动),INDEX(Elasticsearch 将元数据信息和数据从源复制到目标),START(Elasticsearch 正在打开分片供使用)、FINALIZE(最后阶段,清理垃圾)和DONE(恢复已结束)。
我们可以 通过包含 active_only 将索引恢复 API 返回的响应限制为仅当前处于活动恢复中的分片=true 请求中的参数。最后,我们可以通过在 API 调用中添加 detailed=true 参数来请求更详细的信息。
indices 分片存储 API 为我们提供了有关索引分片存储的信息。我们通过对 /_shard_stores REST 端点运行一个简单的命令并提供或不提供逗号分隔的索引名称来使用此 API。
例如,要获取有关所有索引的信息,我们将运行以下命令:
我们还可以获取有关特定索引的信息,例如 library 和 map 索引:
Elasticsearch 返回的响应包含有关每个分片的存储的信息。例如,这是 Elasticsearch 为 library 索引的一个分片返回的内容:
我们可以在 stores 数组中看到有关节点的信息。每个条目包含节点相关信息(分片物理所在的节点)、存储副本的版本和分配,可以取primary的值(对于primary分片)、replica(用于副本)和 unused(用于未分配的分片)。
Elasticsearch 集群中的 索引可以由多个分片构建,每个分片可以有多个副本。将单个索引划分为多个分片的能力使我们可以将数据划分为多个物理实例。我们想要这样做的原因可能不同。我们可能希望并行化索引以获得更高的吞吐量,或者我们可能希望拥有更小的分片以便我们的查询更快。当然,我们可能有太多的文档无法将它们放在一台机器上,因此我们可能需要一个分片。使用副本,我们可以通过拥有每个分片的多个物理副本来并行化查询负载。我们可以说,使用分片和副本,我们可以扩展 Elasticsearch。但是,Elasticsearch 必须弄清楚它应该在集群中的哪个位置放置分片和副本。它需要弄清楚每个分片或副本应该放置在哪些服务器/节点上。
在 Elasticsearch 中使用显式控制分片和副本分配的最常见用例之一是基于时间的数据,即日志。每个日志事件都有一个与之关联的时间戳;但是,大多数组织中的日志数量非常庞大。问题是您需要大量的处理能力来索引它们,但您通常不会搜索历史数据。当然,您可能希望这样做,但这样做的频率将低于查询最新数据的频率。
因此,我们可以将集群分为所谓的两层——冷层和热层。热层包含更强大的节点,具有非常快的磁盘、大量 CPU 处理能力和内存的节点。这些节点将处理大量索引以及对最近数据的查询。另一方面,冷层将包含具有非常大磁盘但速度不是很快的节点。我们不会索引到冷层;我们只会在此处存储我们的历史索引并不时搜索它们。使用默认的 Elasticsearch 行为,我们无法确定分片和副本的放置位置,但 幸运的是,Elasticsearch 允许我们控制这一点。
这个想法是在热节点上创建索引今天数据的索引,当我们停止使用它时(当另一天开始时),我们更新索引设置,以便将其移动到称为冷的层。现在让我们看看如何做到这一点。
因此,让我们将 我们的集群分为两层。我们说的是层,但它们可以是你想要的任何名称,我们就像“层”这个词一样,它是常用的。我们假设我们有六个节点。我们希望将编号为 1 和 2 的更强大的节点放置在名为 hot 的层中,而编号为 3、4、5 和 6 的节点在 CPU 方面更小和内存,但在磁盘空间方面非常大,要放置在称为 cold 的层中。
为了配置,我们将以下属性添加到节点1和2上的elasticsearch.yml配置文件中(那些更强大的):
当然,我们会在节点 3、4、5、6(功能较弱的)上的 elasticsearch.yml 配置文件中添加一个类似的属性:
现在让我们为今天的数据创建 每日索引,名为logs_2015-12-10。正如我们之前所说,我们希望将其放置在热层中的节点上。我们通过运行以下命令来做到这一点:
上述命令将创建 logs_2015-12-10 索引和 index.routing.allocation.include.tier< /code> 属性。我们将此属性设置为 hot 值,这意味着我们要在节点上放置 logs_2015-12-10 索引node.tier 属性设置为 hot。
现在,当 一天结束并且我们需要创建一个新索引时,我们再次将它放在热节点上。我们通过运行以下命令来做到这一点:
最后,我们需要告诉 Elasticsearch 将保存前一天数据的索引移动到冷层。我们通过更新索引设置并将 index.routing.allocation.include.tier 属性设置为 cold 来做到这一点。这是使用以下命令完成的:
运行上述命令后,Elasticsearch 会开始将名为 logs_2015-12-10 的索引重新定位到具有 node.tier 属性在 elasticsearch.yml 文件中设置为 cold,无需我们进行任何手动操作。
与我们指定索引应该放置在哪些节点上的方式相同,我们也可以从索引分配中排除节点。参考前面显示的示例。如果我们不希望将名为 logs_2015-12-10 的索引放置在 node.tier 属性设置为的节点上cold,我们将运行以下命令:
请注意,我们使用 index.routing.allocation.exclude.tier 而不是 属性。index.routing.allocation.include.tier 属性
除了包含和排除规则外,我们还可以指定必须匹配的规则才能将分片分配给给定节点。不同之处在于,当使用 index.routing.allocation.include 属性时,索引将放置在至少与提供的属性值之一匹配的任何节点上。使用 index.routing.allocation.require,Elasticsearch 会将索引放置在具有所有已定义值的节点上。例如,假设我们为 logs_2015-12-10 索引设置了以下设置:
运行上述命令后,Elasticsearch 只会将 logs_2015-12-10 索引的分片放在具有 node.tier
属性设置为 hot 并且 node.disk_type 属性设置为 ssd。
除了 向节点配置添加一个特殊参数,我们可以使用 IP 地址来指定我们想要从分片和副本中包含或排除哪些节点分配。为了做到这一点,而不是使用 index.routing.allocation.include.tier 或 的 属性,我们应该使用 tier 部分class="literal">index.routing.allocation.exclude.tier_ip。例如,如果我们希望我们的 logs_2015-12-10 索引仅放置在具有 10.1.2.10 的节点上和 10.1.2.11 IP 地址,我们将运行以下命令:
除了已经描述的分配过滤方法之外,Elasticsearch 还为我们提供了基于磁盘的分片分配规则。它允许我们根据节点的磁盘使用情况设置分配规则。
有四个属性控制基于磁盘的分片分配的行为。所有这些都可以动态更新或在 elasticsearch.yml 配置文件中设置。
其中第一个是cluster.info.update.interval,默认设置为30秒并定义 Elasticsearch 更新节点上磁盘使用信息的频率。
第二个属性是 cluster.routing.allocation.disk.watermark.low,默认设置为 0.85。这意味着 Elasticsearch 不会将新分片分配给使用超过 85% 磁盘空间的节点。
第三个属性是 cluster.routing.allocation.disk.watermark.high,它控制 Elasticsearch 何时开始从给定节点重新定位分片。它默认为 0.90,这意味着当给定节点上的磁盘使用率等于或超过 90% 时,Elasticsearch 将开始重新分配分片。
cluster.routing.allocation.disk.watermark.low 和 cluster.routing.allocation.disk.watermark.high 属性可以设置为百分比值(如0.60,表示60%)和绝对值(如600mb,表示 600 兆字节)。
最后,最后一个属性是cluster.routing.allocation.disk.include_relocations,默认设置为true。它告诉 Elasticsearch 考虑尚未复制到节点的分片,但 Elasticsearch 正在这样做。默认开启此行为意味着基于磁盘的分配机制在可用磁盘空间(当分片重定位时)时会更加悲观,但我们不会遇到无法重定位分片的情况,因为关于磁盘空间的假设是错误的。
在中,除了指定分片和副本分配外,我们还可以指定单个索引可以在单个节点上放置的最大分片数。例如,如果我们希望我们的 logs_2015-12-10 索引每个节点只有一个分片,我们将运行以下命令:
该属性可以放在 elasticsearch.yml 文件中,也可以使用前面的命令在实时索引上更新。请记住,如果 Elasticsearch 无法分配所有主分片,您的集群可能会保持红色状态。
Elasticsearch的分配机制可以被限制,这意味着我们可以控制Elasticsearch在分片分配和恢复过程中将使用多少资源。我们有五个要控制的属性,如下所示:
cluster.routing.allocation.node_concurrent_recoveries:该属性定义了一个节点上可能同时发生多少并发分片恢复。默认为2如果您希望在单个节点上同时恢复更多分片,则应增加此值。但是,增加此值将导致恢复期间更多的资源消耗。另外,请记住,在副本恢复过程中,数据将通过网络从其他节点复制,这可能会很慢。cluster.routing.allocation.node_initial_primaries_recoveries:此属性默认为 4,并定义在给定节点上同时恢复多少个主分片。因为主分片恢复使用本地磁盘中的数据,所以这个过程应该非常快。cluster.routing.allocation.same_shard.host:一个Boolean属性,默认为false< /code> 并且仅在同一台机器上启动多个 Elasticsearch 节点时适用。当设置为 true 时,这将强制 Elasticsearch 检查同一分片的物理副本是否存在于单个物理机器上。默认的false值表示不进行检查。indices.recovery.concurrent_streams:这是用于从其他节点复制数据的网络流的数量,可以在单个节点上同时使用。流越多,复制数据的速度就越快,但这会导致更多的资源消耗。此属性默认为3。indices.recovery.concurrent_small_file_streams:这类似于indices.recovery.concurrent_streams属性,但定义了 Elasticsearch 并发数据流的数量将用于复制小文件(小于5mb的文件)。此属性默认为2。
这允许 我们根据主机名和主机地址执行检查,以防止在单个主机上分配同一分片的多个实例。这默认为 false,这意味着默认情况下不执行任何检查。此设置仅适用于在同一台机器上启动多个节点的情况。
除了每个索引分配设置外,Elasticsearch 还允许我们控制分片和基于集群范围的索引分配——所谓的分片分配意识。当我们在不同的物理机架中有节点并且我们希望将分片和副本放置在不同的物理节点中时,这尤其有用。
让我们从一个简单的例子开始。我们假设我们有一个由四个节点组成的集群。每个节点位于不同的物理机架中。说明这一点的简单图形如下:
正如您 所见,我们的集群是由四个节点构建的。每个节点都绑定到一个特定的 IP 地址,每个节点都有 tag 属性和 group 属性(添加到 elasticsearch.yml 作为 node.tag 和 node.group 属性)。该集群将用于展示分片分配过滤的工作原理。 group 和 tag 属性可以任意命名,您只需在所需的属性名称前加上 node 名称,例如,如果您想使用 party 属性名称,您只需添加 node.party:party1 到你的 elasticsearch.yml。
分配意识允许我们使用通用参数配置分片及其副本分配。为了说明分配感知是如何工作的,我们将使用我们的示例集群。为了使示例正常工作,我们应该将以下属性添加到 elasticsearch.yml 文件中:
这将告诉 Elasticsearch 使用 node.group 属性作为感知参数。
Note
您可以在设置 cluster.routing.allocation.awareness.attributes 属性时指定多个属性。例如:
cluster.routing.allocation.awareness.attributes: group, node
在此之后,让我们启动前两个节点,即 node.group 参数等于 < code class="literal">groupA,让我们通过运行以下命令来创建索引:
在这个命令之后,我们的两节点集群或多或少看起来像这样:
如您所见,索引在两个节点之间平均分配。现在让我们看看当我们启动其余节点时会发生什么(那些 node.group 设置为 groupB 的节点):
注意的区别——主分片没有从原来的分配节点移动,但是副本分片被移动到具有不同node.group 值。完全正确;当使用分片分配感知时,Elasticsearch 不会将同一索引的主分片和副本分配给用于确定分配感知的属性值相同的节点(在我们的例子中是 node.group)。
当我们提前知道我们的意识属性可以取多少值并且我们不想要比需要更多的副本例如,不要在我们的集群中分配太多副本,以免我们的集群过载。为此,我们可以强制分配意识仅对某些属性有效。我们可以使用 cluster.routing.allocation.awareness.force.zone.values 属性指定这些值,并为其提供逗号分隔值的列表。例如,如果我们希望分配感知只使用 groupA 和 groupB 值">node.group 属性,我们将以下内容添加到 elasticsearch.yml 文件中:
Elasticsearch 允许我们为整个集群或索引级别配置分配。在集群分配的情况下,我们可以使用属性前缀:
cluster.routing.allocation.includecluster.routing.allocation.requirecluster.routing.allocation.exclude
当涉及到特定于索引的分配时,我们可以使用以下属性前缀:
index.routing.allocation.includeindex.routing.allocation.requireindex.routing.allocation.exclude
前面提到的前缀可以与我们在 elasticsearch.yml 文件中定义的属性一起使用(我们的 tag 和 < code class="literal">group 属性)和一个名为 _ip 的特殊属性,允许我们匹配或排除节点 IP 地址的使用,例如例如,像这样:
如果我们想要包含具有匹配 groupA 值的 group 属性的节点,我们将设置以下属性:
请注意,我们使用了 cluster.routing.allocation.include 前缀,并将其与属性的名称连接起来,即 组 在我们的例子中。
仔细看前面的参数,你会发现一共有三种:
include:此 类型将包含所有定义了此参数的节点。如果多个include条件是可见的,那么在分配分片时将考虑所有至少匹配这些条件之一的节点。例如,如果我们在配置中添加两个cluster.routing.allocation.include.tag参数,其中一个参数的属性值为node1和第二个使用node2值,我们最终会将索引(实际上是它们的分片)分配给第一个和第二个节点(从左到右计数)。总而言之,具有include allocation参数类型的节点在选择放置分片的节点时会被 Elasticsearch 考虑,但是 这并不意味着 Elasticsearch 会将分片放入其中。require:这个参数是在Elasticsearch 0.90类型的分配过滤器中引入的,需要所有节点具有与此属性的值匹配的值。例如,如果我们在配置中添加一个cluster.routing.allocation.require.tag参数,其值为node1并且cluster.routing.allocation.require.group参数的值是groupA,我们最终会得到只分配给第一个节点(IP 地址为192.168.2.1的节点)。exclude:这个 参数允许我们从分配过程中排除具有给定属性的节点。例如,如果我们将cluster.routing.allocation.include.tag设置为groupA,我们最终会分配索引仅适用于 IP 地址为192.168.3.1和192.168.3.2的节点(我们示例中的第三个和第四个节点)。
我们想要讨论的 最后一件事是在节点之间手动移动分片的能力。 Elasticsearch 公开了 _cluster/reroute REST 端点,它允许我们控制它。可以使用以下操作:
将分片从一个节点移动到另一个节点
取消分片分配
强制分片分配
现在让我们仔细看看前面的所有操作。
假设我们有 两个节点,分别称为 es_node_one 和 es_node_two,我们有两个由 Elasticsearch 放置在第一个节点上的 shop 索引分片,我们想将第二个分片移动到第二个节点。为此,我们可以运行以下命令:
我们指定了 move 命令,它允许我们移动由 index 属性指定的索引的分片(和副本) . shard 属性是我们想要移动的分片数量。最后,from_node 属性指定了我们要从中移动分片的节点的名称,to_node 属性指定了我们希望放置分片的节点的名称。
默认情况下,默认情况下,Elasticsearch 会尝试使分片及其副本在集群中保持均匀平衡。这种行为在大多数情况下是好的,但有时我们想要控制这种行为——例如,在滚动重启期间。我们不想在重启一两个节点时重新平衡整个集群。在本节中,我们将研究如何避免集群重新平衡并深入控制此过程的行为。
想象一下这样一种情况,您知道您的网络可以处理非常大量的流量或与之相反的情况——您的网络被广泛使用并且您希望避免过多的负载。另一个示例是,您可能希望减少在全集群重启后施加在 I/O 子系统上的压力,并且希望同时初始化更少的分片和副本。这只是重新平衡控制可能很方便的两个示例。
再平衡是在我们集群的不同节点之间移动分片的过程。正如我们已经提到的,在大多数情况下都可以,但有时您可能希望完全避免这种情况。例如,如果我们定义了分片的放置方式并希望保持这种方式,我们可能希望避免重新平衡。但是,默认情况下,每当集群状态发生变化并且 Elasticsearch 认为需要重新平衡时,Elasticsearch 将尝试重新平衡集群(并且延迟超时已通过,如讨论的那样)在第9章网关和恢复模块部分>, Elasticsearch 集群详解)。
我们已经 知道我们的索引是由分片和副本构建的。主分片或仅分片是最先获取数据的分片。副本是主副本的物理副本,并从中获取数据。当所有主分片都分配给集群中的节点时,您可以认为集群已准备好使用 - 一旦达到黄色健康状态。但是,Elasticsearch 可能仍会初始化其他分片——副本。但是,您可以使用您的集群并确保您可以搜索整个数据集并发送索引更改命令。然后将正确处理命令。
Elasticsearch 让 我们使用可以在 elasticsearch.yml
文件或使用 Elasticsearch REST API(如 更新设置 API 部分所述" linkend="ch09">第 9 章,Elasticsearch 集群详解)。
cluster.routing.allocation.allow_rebalance 属性允许我们指定何时允许重新平衡。此属性可以采用以下值:
always:一旦需要,将允许重新平衡indices_primaries_active:当所有的主分片都被初始化时允许再平衡indices_all_active:默认值,表示在所有分片和副本初始化时允许重新平衡
cluster.routing.allocation.allow_rebalance 属性可以在 elasticsearch.yml 配置文件中设置,也可以动态更新。
cluster.routing.allocation.cluster_concurrent_rebalance 属性允许我们指定在整个集群中一次可以在节点之间移动多少个分片。如果您有一个由许多节点构建的集群,则可以增加此值。此值默认为 2。如果您希望更快地执行再平衡,您可以增加默认值,但这会给您的集群资源带来更大的压力并且会影响索引和查询. cluster.routing.allocation.cluster_concurrent_rebalance 属性可以在 elasticsearch.yml 配置文件中设置,也可以动态更新。
cluster.routing.allocation.enable 属性允许我们指定 Elasticsearch 何时允许重新平衡哪些分片。此属性可以采用以下值:
all:默认行为,告诉 Elasticsearch 重新平衡集群中的所有分片primaries:此值仅允许重新平衡主分片replicas:此值仅允许重新平衡副本分片none:此值禁用集群中所有索引的所有类型分片的重新平衡
cluster.routing.allocation.enable 属性可以在 elasticsearch.yml 配置文件中设置,也可以动态更新。
Elasticsearch Admin API 非常广泛,几乎涵盖了 Elasticsearch 架构的每个部分:从有关 Lucene 的低级信息到有关集群节点的高级信息和他们的健康。所有这些信息都可以使用 Elasticsearch Java API 和 REST API 获得。然而,返回的数据,即使它是一个 JSON 文档,用户可读性也不是很好,至少在给出的信息量方面是这样。
正因为如此,Elasticsearch 为我们提供了更加人性化的 API——Cat API。特殊的 Cat API 以简单文本、表格格式等形式返回数据——它提供通常无需任何进一步处理即可使用的聚合数据。
Cat API 的基本 端点非常明显:它是/_cat。如果没有任何参数,它会显示此 API 的所有可用端点。我们可以通过运行以下命令来检查:
Elasticsearch 返回的响应应该与以下响应相似或相同(取决于您的 Elasticsearch 版本):
使用 Cat API 就像对前面提到的 REST 端之一运行 GET 请求一样简单-点。例如,要获取有关集群状态的信息,我们可以运行以下命令:
Elasticsearch 对上述命令返回的响应应该类似于以下命令,但当然,这取决于您的集群:
这很干净而且很好。因为它是表格格式,所以也很容易在 grep、awk 或 等工具中使用响应class="literal">sed – 为每位管理员提供的一套标准工具。一旦你知道它的全部内容,它也更具可读性。
要添加描述每个列用途的标题,我们只需要添加一个额外的 v 参数,就像这样:
每个 Cat API 端点都有自己的参数,但它们之间有一些共同的选项:
v:这会在响应中添加一个标题行,其中包含所呈现项目的名称。h:这允许我们只显示选择的列,例如h=status,node.total,shards,pri。help:这列出了该特定端点能够显示的所有可能的列。该命令显示参数的名称、其缩写和描述。bytes:这是表示以字节为单位的值的信息格式。正如我们之前所说,Cat API 旨在供人类使用,因此,默认情况下,这些值以人类可读的形式表示,例如:3.5kB或40GB。bytes选项允许为所有数字设置相同的基数,因此排序或数字比较会更容易。例如,bytes=b以字节表示所有值,bytes=k以千字节表示,等等。Note
对于 每个 Cat API 端点的完整参数列表,请参阅官方 Elasticsearch 文档位于:https:// www.elastic.co/guide/en/elasticsearch/reference/2.2/cat.html。
我们编写本书时,Cat API 有 22 个端点。我们不想全部描述它们——这将是文档中包含的信息的重复,而且没有任何意义。但是,我们不想在没有关于 Cat API 使用的示例的情况下离开本节。因此,我们决定展示与 Elasticsearch 公开的标准 JSON API 相比,使用 Cat API 获取信息的难易程度。
第一个例子展示了获取集群中哪个节点是主节点的信息是多么容易。通过调用 /_cat/master REST 端点,我们可以获得有关节点的信息,以及其中一个当前被选为主节点的信息。例如,让我们运行以下命令:
Elasticsearch 为我的本地双节点集群返回的响应如下所示:
正如您在响应中看到的那样,我们已经获得了关于哪个节点当前被选为主节点的信息:我们可以看到它的标识符、IP 地址和名称。
/_cat/nodes REST 端点提供有关集群中所有节点的信息。让我们看看运行以下命令后 Elasticsearch 会返回什么:
在前面的示例中,我们使用了从该端点的大约 70 个选项中选择我们想要获取的信息的可能性。我们选择只获取节点名称、它的角色(节点是数据节点还是客户端节点)、节点负载及其正常运行时间。
Elasticsearch 返回的响应如下所示:
有时, 可能需要准备 Elasticsearch 来处理您的查询。可能是因为您严重依赖字段数据缓存并且您希望在生产查询到达之前加载它,或者您可能希望预热操作系统的 I/O 缓存以便从缓存中读取数据索引文件。不管是什么原因,Elasticsearch 允许我们对我们的类型和索引使用所谓的预热查询。
warming 查询只不过是存储在 Elasticsearch 中称为 _warmer 的特殊类型中的常见查询。假设我们有以下要用于热身的查询:
要将 前面的查询存储为我们的库索引的预热查询,我们将运行以下命令:
前面的命令会将我们的查询注册为带有 tags_warming_query 名称的预热查询。您可以对索引进行多个预热查询,但每个查询都需要有一个唯一的名称。
我们不仅可以为整个索引定义预热查询,还可以为其中的特定类型定义预热查询。例如,要将我们之前显示的查询存储为 book 类型的预热查询在 library 索引中,运行前面的命令不是 /library/_warmer URI,而是 /library/book/_warmer。因此,整个命令将如下所示:
添加预热查询后,在 Elasticsearch 允许搜索新段之前,它将通过在该段上运行定义的预热查询来预热。这允许 Elasticsearch 和操作系统缓存数据,从而加快搜索速度。
正如我们阅读全文搜索部分="link" href="#" linkend="ch01">第 1 章,Elasticsearch Cluster 入门,Lucene 将索引到称为段的部分,一旦写入就无法更改。每个新的提交操作都会创建一个新的段(如果段数太多,最终会合并),Lucene 使用该段进行搜索。
为了 为我们的索引获取特定的预热查询,我们只需要知道它的名称。例如,如果我们想为 library 索引获取名为 tags_warming_query 的预热查询,我们将运行以下命令:
Elasticsearch 返回的结果如下:
我们还可以使用以下命令获取索引和类型的所有预热查询:
最后,我们还可以获得所有以给定前缀开头的预热查询。例如,如果我们想要获取以 tags 前缀开头的 library 索引的所有预热查询,我们将运行以下命令:
删除 一个暖化查询与获取一个非常相似;我们只需要使用 DELETE HTTP 方法。要从我们的索引中删除特定的预热查询,我们只需要知道它的名称。例如,如果我们想为 library 索引删除名为 tags_warming_query 的预热查询,我们将运行以下命令:
我们还可以使用以下命令删除索引的所有预热查询:
最后,我们还可以删除所有以给定前缀开头的预热查询。例如,如果我们要删除所有以 tags 前缀开头的 library 索引的预热查询,我们将运行以下命令:
要 完全禁用预热查询,但要将它们保存在 _warmer 索引中,您应该设置 index.warmer.enabled 配置属性为 false (将此属性设置为 true 将导致启用预热功能)。此设置可以放在 elasticsearch.yml 文件中,也可以在实时集群上使用 REST API 进行设置。
例如,如果我们想禁用 library 索引的预热功能,我们将运行以下命令:
最后,我们 应该问自己一个问题:哪些查询应该被视为变暖的候选。通常,您需要选择执行成本高昂的和需要填充缓存的。因此,您可能希望根据索引中的字段选择包含聚合和排序的查询。这将迫使操作系统加载保存与此类查询相关的数据的索引部分,并提高运行的连续查询的性能。除此之外,父子查询和嵌套查询也是潜在的预热对象。您还可以通过查看日志来选择其他查询,并找出您的性能没有达到您想要的水平。这样的查询也可能是热身的完美候选者。
例如,假设我们在 elasticsearch.yml 文件中设置了以下日志记录配置:
我们在 logging.yml 配置文件中设置了以下日志级别:
注意 index.search.slowlog.threshold.query.trace 属性设置为 1s 并且 index.search.slowlog 日志记录级别设置为 TRACE。这意味着每当一个查询执行超过一秒(在一个分片上,而不是总共),它都会被记录到慢日志文件中(其名称由 index 配置部分)。例如,可以在慢速日志文件中找到以下内容:logging.yml 配置文件的 _search_slow_log_file
如您所见,在前面的日志行中,我们有查询时间、搜索类型和查询源,它向我们展示了执行的查询。
当然,配置中的值可能不同,但慢日志可能是运行时间过长的查询的宝贵来源,可能需要定义一些预热;也许这些是父子查询,需要获取一些标识符才能更好地执行,或者您可能正在使用第一次执行时昂贵的过滤器。
您应该记住一件事:不要用太多的预热查询使您的 Elasticsearch 集群过载,因为您最终可能会花费太多时间来预热 处理您的生产查询。
当 在 Elasticsearch 中使用多个索引时,您有时可能会忘记它们。想象一下,您通常将日志存储在索引或基于时间的数据中。通常,这种情况下的数据量非常大,因此,以某种方式划分数据是一个很好的解决方案。通过为一天的日志创建单个索引来获得此类数据的逻辑划分(如果您对 用于管理日志的开源解决方案感兴趣,在 https://www.elastic.co/ 查看 Elasticsearch 套件中的 Logstash产品/logstash)。
但是,一段时间后,如果我们保留所有索引,我们将开始在处理所有这些方面遇到问题。应用程序需要处理所有信息,例如将数据发送到哪个索引、查询哪个索引等等。在别名的帮助下,我们可以将其更改为使用单个名称,就像使用单个索引一样,但我们将使用多个索引。
什么是 索引别名?它是一个或多个索引的附加名称,允许我们通过使用这些附加名称引用它们来使用这些索引。一个别名可以有多个索引,反之亦然;单个索引可以是多个别名的一部分。
但是,请记住,您不能将具有多个索引的别名用于索引或实时 GET 操作。如果你这样做,Elasticsearch 会抛出异常。不过,我们仍然可以使用仅链接到单个索引的别名来进行索引。这是因为 Elasticsearch 不知道应该在哪个索引中索引数据或应该从哪个索引中获取文档。
要创建 索引别名,我们需要对POST 方法literal">_aliases 具有已定义操作的 REST 端点。例如,以下请求将创建一个名为 week12 的新别名,其中将包含名为 day10、day11 和 day12(我们需要先创建这些索引):
如果我们的 Elasticsearch 集群中不存在 week12 别名,则前面的命令将创建它。如果它 存在,该命令只会将指定的索引添加到它。
我们将对三个索引进行搜索,如下所示:
如果一切顺利,我们可以改为如下运行它:
这不是更好吗?
有时我们有一组索引,其中每个索引都提供独立的信息,但有些查询应该遍历所有索引;例如,我们有国家的专用索引(country_en、country_us、country_de 等)。在这种情况下,我们将通过将它们全部分组来创建别名:
最后一个命令只创建了一个别名。 Elasticsearch 允许您将其重写为不那么冗长的内容:
当然,您也可以从别名中删除索引。我们可以这样做,就像我们向别名添加索引一样,但是我们使用 remove 命令而不是 add 命令.例如,要从 week12 索引中删除名为 day9 的索引,我们将运行以下命令:
在中,除了在别名中添加或删除索引之外,我们和我们使用 Elasticsearch 的应用程序可能需要检索集群中可用的所有别名或所有可用的别名。索引连接到的别名。为了检索这些别名,我们使用 HTTP GET 命令发送请求。例如,以下命令获取 day10 索引的所有别名,第二个命令将获取所有可用别名:
第二条命令的响应如下:
您还可以使用 _alias 端点从给定索引中获取所有别名:
别名 的使用方式类似于 SQL 数据库中视图的使用方式。您可以使用完整的 Query DSL(在 第 3 章中详细讨论,搜索您的数据)并将您的过滤器应用于所有计数、搜索、按查询删除等。
让我们看一个例子。想象一下,我们想要为某个客户端返回数据的别名,以便我们可以在我们的应用程序中使用它。假设我们感兴趣的客户端标识符存储在 clientId 字段中,我们对 12345 客户端感兴趣。因此,让我们使用我们的数据索引创建名为 client 的别名,它将自动应用对 clientId 的查询:
因此,当使用定义的别名时,您将始终通过术语查询过滤您的请求,以确保 所有文档都具有 clientId 字段中的 >12345 值。
在第2章的路由简介部分,索引你的数据,我们谈到了路由。类似于 使用过滤的别名,我们可以为别名添加路由值。想象一下,我们正在使用基于用户标识符的路由,并且我们希望将相同的路由值与我们的别名一起使用。因此,对于名为 client 的别名,我们将使用 12345、12346 的路由值 和 12347 用于查询,只有 12345 用于索引。为此,我们将使用以下命令创建一个别名:
这样,当我们使用 client 别名索引我们的数据时,将使用 index_routing 属性指定的值。在查询时,将使用 search_routing 属性指定的值。
还有一件事。请查看发送到先前定义的别名的以下查询:
用作路由值的值将是 12345。这是因为 Elasticsearch 将采用 search_routing 属性和查询路由参数的公共值,在我们的例子中是 12345。
在本章中,我们讨论了 Elasticsearch 管理。我们首先学习如何执行索引备份以及如何使用其 API 监控集群健康和状态。我们控制了集群分片重新平衡,并学习了如何根据需要调整分片分配。我们已经使用 CAT API 以人类可读的形式获取有关 Elasticsearch 的信息,并且我们已经预热了我们的查询以使其更快。最后,我们使用别名来更好地管理我们的索引并具有更大的灵活性。
在本书的下一章也是最后一章中,我们将关注一个假设的在线图书馆商店,看看如何让 Elasticsearch 在实践中发挥作用。我们将从简要介绍和硬件注意事项开始。我们将调整 Elasticsearch 的单个实例并通过讨论其每个部分并提供适当的架构来正确配置我们的集群。我们将垂直扩展集群并为高查询和高索引负载做好准备。最后,我们将学习如何监控这样一个准备好的集群。
