读书笔记《elasticsearch-blueprints》处理基于时间的数据
在本章中,我们将探讨在 Elasticsearch 中使用常规索引时所面临的困难的解决方案。本章将向您介绍以下主题:
使用基于时间的常规计划外索引数据遇到的问题
在 Elasticsearch 中索引基于时间的数据
覆盖未来指数的默认值
覆盖索引级、类型级和字段级设置
在基于时间的数据中进行高性能搜索
调整最近数据的性能
在前面的章节中,我们看到了如何在 Elasticsearch 中索引数据。现在我们已经完成了一种非常基本的索引形式,让我们来看看普通方法的优缺点。在迄今为止的索引方法中,我们看到当我们创建索引时,我们还定义了与其关联的分片数量。一旦我们创建了一个索引,我们就不能增加或减少它的分片数量。
您可能还记得,碎片是包含我们数据的地方。但是,一旦我们在创建索引时指定了 分片的数量,以后就无法增加或减少该数量。因此,只有当我们事先知道我们创建的索引中将包含多少数据时,这种方法基本上是可以的。尽管如此,这不一定是很多次的情况。当被索引的数据是基于时间的时,这种索引的主要问题就出现了。
让我们在细节中探讨问题,即基于时间的数据何时出现。基于时间的数据是我们随着时间不断添加文档的地方。最初,可能没有大量数据,但随着时间的推移,可能会有大量数据。
Twitter 收听工具可以作为一个完美的例子,说明如何展示由 正常索引方式引起的问题。假设我们计划对来自某个地理位置(例如美国)的所有推文进行索引。如果我们使用单个索引来存储所有这些推文,在某个时间点,系统将会崩溃,因为我们无法扩展超出索引定义的分片数量。
因此,我们必须找到一种方法来解决索引创建中的先前问题。存储数据的最佳方式是在每个时间范围内为时间数据创建一个索引。在这里,根据数据量,我们可以每小时、每天、每周甚至一个月拥有一个索引。这有助于轻松进行数据管理,还可以解决由于 Elasticsearch 中的单一索引可能导致的问题。
下图显示了一种索引创建方法,其中索引是每天创建和命名的。这里,在下面的例子中,命名为YYYY-MM-DD
,即年-月-日格式,前缀logstash
:
在基于时间的数据中,我们注意到我们在每个时间范围内创建了一个新索引。假设索引每个时间范围需要自定义设置而不是默认设置,手动创建所有未来索引是不可能的。由于 Elasticsearch 在索引时自动创建缺少的索引,使用默认设置和映射,我们需要一些机制来覆盖默认值。
Elasticsearch 允许我们基于 < /a>模式。
模板创建是 Elasticsearch 中最重要的功能之一。它广泛用于与基于时间的数据索引。我们为索引使用模板创建的主要原因是大多数时候,我们会为不同的数据集使用自定义设置和映射。索引模板允许我们通过提供索引名称模式来定义索引的默认设置。所以,假设我们每天有一个索引,格式是 logstash-YYYY-MM-DD
。假设我们想要一个只有 2 个分片而不是 5 个分片的索引,这是默认设置。我们可以为 logstash-*
模式分配一个模板。每次插入文档并且缺少文档的索引时,模式都会从模板中获取默认值。让我们看看如何创建模板:
在这里,创建了一个名为 logstash
的模板,我们在其中定义了自定义设置和映射。我们定义了一个 template
字段,它定义了它将匹配并应用模板设置的所有索引名称模式。在此示例中,设置和映射将应用于与 logstash-*
模板匹配的任何索引名称。也就是说,如果有名称的索引,logstash-23-06-2015
、logstash-master
和logstash:server
,模板设置和映射将应用于前两个索引,因为它与我们模板中定义的模式匹配。
我们在前面的模板定义代码中有一个 order
字段,它的值是 0
。 order 值设置 Elasticsearch 首选创建的模板的优先级。
在 Elasticsearch 中使用多个模板创建索引是一种非常常见的实践。您可能经常会问这样的问题,如果此类模板中存在冲突的设置/映射会发生什么?让我们看看这样一个场景。假设我们有两个定义如下的模板:
模板 1
:模板 2
:
在这种情况下,名为 logstash-21-04-2015
和 logstash-server
的索引属于这两个模板。但是,模板 logstash1
和 logstash2
的设置有
number_of_shards
字段中的冲突。因此,弄清楚 Elasticsearch 将哪个模板应用于索引会很有趣。
如果多个模板匹配一个索引名称,所有匹配的模板设置将被合并以获取要创建的索引的设置。如果发生冲突,订单号将用于解决冲突。
如您所见,logstash1
模板已按 0
的顺序定义,而 logstash2
模板已按 1
的顺序定义。 order
字段的值越小,优先级越高。这意味着在发生冲突的情况下,logstash1
模板的优先级高于 logstash2
,这意味着冲突的字段值将从具有更高优先级的索引中获取,其余字段将被合并。
现在,有时,要求创建的所有索引都应具有一组特定的映射/设置。
这可以通过创建适用于所有索引的索引模板变得简单。为此,我们可以将 template
字段定义为 *
,这将使模板能够将其所有设置/映射应用于索引用任何名字。
此类索引模板的示例如下所示:
使用索引模板,我们还可以覆盖索引下类型的默认值。默认情况下,对于 所有索引类型,_all
将被启用。在许多情况下,这可能会浪费资源。在模板中,我们可以定义名称已知的类型的映射,以及将来自动创建的任何索引类型的默认值。
一个例子是:
在这里,我们有一个名为 data-index
的索引。假设索引data-index
下有三种类型,分别命名为type1
、type2< /code> 和
type3
以及对于 type1
,我们需要启用 _all
字段。在前一种情况下,我们默认禁用
_all
字段。为了启用type1
中的_all
字段,我们单独提及并指定启用< /code> 为
true
。
现在使用此设置,除了 type1
之外,_all
将对所有其他类型禁用。
在文档索引中,如果映射中未定义字段,则根据数据“猜测”该字段的类型。这很好用,但在许多情况下,我们可能需要覆盖此行为。最好的例子是自定义格式的时间字段。
当我们需要动态添加新变量时,动态模板用于动态映射。动态模板允许我们定义新生成的字段的映射。可以根据数据类型或字段名称将映射应用于新生成的字段。
这种动态模板的示例代码如下:
在前面的示例代码中,我们为字符串字段定义了两个名为 customdate
和 customstring
的模板。
customdate
的作用是检查所有以 date_*
开头的字段。然后为匹配的字段提供映射类型 date
,该映射类型定义了特定格式。这实际上是将 date_*
字段过滤为日期格式。
同样,在 customstring
模板中,match
是为 *
定义的,即是,所有字段,它会将映射应用于所有字段。映射可以为此目的使用任何分析器,甚至是我们创建的自定义分析器。
模板按出现的顺序进行检查。由于 customdate
被放在首位,带有 date_*
的字段首先被映射,然后,customstring
模板被选中。
查询基于时间的数据的特殊性质在于,它主要是面向时间的。在大多数查询中,都会有一个确定的时间范围,主要指向最近的数据。让我们看看如何在搜索中利用这一点。
在前面的 部分中,我们看到了如何使用模板为基于时间的数据创建自定义索引,以及如何覆盖设置和映射。正如我们在上一节中看到的,最重要的应用是对我们感兴趣的索引进行建模以进行查询。这意味着,我们可以从整个基于时间的索引池中选择特定的索引,并对选定的几个进行操作。
假设我们有许多 logstash
索引以它们创建的那一周命名。所以,在一年内,比如 2014 年,总共有 52 个索引.假设我们还创建了 logstash-YYYY-WW
格式的索引名称,即年-周数字格式。因此,示例索引的名称为 logstash-2014-21
,这意味着该索引是为 2014 年第 21 周的数据创建的。
让我们看一个实时场景并了解它是如何工作的。假设每天有一个索引,其中索引名称的格式为 logstash-YYYY-MM-DD
。现在,让我们看看我们如何运行一个查询,该查询需要在过去 3 天中所有具有公司字段为 cisco
的文档:
如您所见,我们在整个索引集上运行查询,而不仅仅是在我们需要的索引上运行 。因此,我们在搜索上不必要地浪费了带宽。一个好的解决方法是只选择我们想要搜索的索引。
因此,可以以更有效的方式对前面的查询进行改造,如下所示(假设今天的日期是 2015-03-05):
在这里,通过确保我们只搜索所需的索引,我们获得了更好的性能。
在处理 与基于时间的数据时,通常会注意到最有用的数据是当前数据。这使得旧数据与我们的目的不太相关。因此,随着时间的推移,过去数据的相关性会迅速下降,我们索引的数据在集群中没有被使用就存在。这种情况对资源不是很友好,因为会有很多未使用的数据存储用于无目的或无目的的使用。
我们可以可视化不同级别的归档,如下所示:
将最热索引保留在具有良好硬件(分片过滤)的机器中。
在完成写入的索引上运行优化的 API。
关闭即时搜索不需要的索引。
拍摄快照并存档旧索引。
最后,删除不再需要的索引。
对于基于时间的数据,最近的指数使用更频繁或更相关。换句话说,在给定时间,数据流将使用基于天、周或月的特定索引。该索引将成为所有新文档的目标,并且大多数 查询也将命中相同的索引。因此,为包含我们大量使用的索引的节点分配最佳资源是一个好主意。
这种方法的问题在于,Elasticsearch 很难识别我们为频繁使用的索引分配了哪个节点。为了让 Elasticsearch 了解哪个节点,我们可以在节点启动或启动时为其指定标签。这可以在 Elasticsearch 的配置文件中定义,如下所示:
这里,memory
是任意键;我们可以给它任何我们想要的名字。这些键值对充当一组节点的标识符。因此,我们可以根据 best_node
键的不同值对不同的节点进行分组。具有相同内存值的所有节点都属于一组。使用这种方法,我们可以根据硬件手动对机器进行分组。
假设我们有名为 logstash-02-07-2015
和 logstash-02-06-2015
的索引。假设第一个索引是我们当前的索引,我们需要分配具有最佳资源索引的节点。在这里,第二个索引 logstash-02-06-2015
是一个旧索引,我们暂时不会大量使用它。
以下是我们如何让 Elasticsearch 理解相同:
在前面的 代码中,对于索引的创建,我们指定数据流到节点 具有 best_node" : 16G"
标签,这是我们最好的资源。
我们看到了如何将数据移动到最佳节点;现在,正如我们之前提到的,旧数据可能不太有用,我们可以看到旧索引如何移动到资源较少或中等资源的节点。
首先,定义节点的标签(这里,资源较少):
然后,在我们的示例中,旧索引是 logstash-02-06-2015
。现在更新该索引的设置,如下所示:
现在,索引 logstash-02-06-2015
被移动到匹配 memory" : "8G"
标签的节点. 这样,当前的索引,即写重读和重读被分配给有的机器。
下图显示了分片分配中发生的情况的图形表示:
随着时间的推移,驻留在旧索引中的文档将被利用到 级别,甚至可能无法访问。这些索引将使用我们的 CPU、主内存和其他资源,因为它们驻留在其节点的磁盘中。这种情况并不健康,因为我们只是将资源用于未使用或未访问的数据。 Elasticsearch 通过让我们“关闭”旧索引为我们提供了一种管理这种情况的方法。
关闭索引意味着该索引仍将保留在集群中,除了正在使用的磁盘空间之外没有任何资源。关闭索引的优点是重新打开它比从备份中恢复索引要容易得多。
我们可以使用 close
API 关闭该索引:
如前所述,指定的索引将存储在磁盘中,但所有的读/写操作都会被阻止。
如果我们想重新打开索引,我们可以使用 open
API:
Curator 是由 Elasticsearch 社区用 Python 开发的工具,用于在 Elasticsearch 中管理或管理 基于时间的索引。 curator 的主要目的是对基于时间的建模索引进行操作。比如说,我们想要优化所有比今天更早的索引。我们将需要查询并了解哪些所有索引都处于这种情况下,然后,我们需要为每个索引运行命令。这可能是一个耗时的过程。为此,我们可以使用 curator 并要求它为我们执行基于时间的索引的任务。例如,我们可以告诉 curator 删除/优化超过一天的索引。
Curator 了解各种基于时间的索引名称格式,一旦它们作为命令行参数给出。使用相同的,您可以发出各种命令。
通过使用curator,我们可以对索引进行前面提到的操作,比如:
分片分配
指数的开市和收市
优化
快照创建