“基本技能”弹性搜索指数生命周期管理(附代码)

索引是弹性搜索中最重要的概念之一,也是整个弹性搜索操作的基础。Elasticsearch为Elasticsearch生命周期管理提供索引API,包括索引创建、查询、删除和设置、索引冻结和解冻、拆分和收缩等。掌握索引管理是Elasticsearch开发、运维的基础能力,也有助于后期优化Elasticsearch。

要创建一个索引,可以使用Elasticsearch提供的API,其格式如下:

其中是要创建的索引的名称,是必需的参数,并且所有字母都必须小写。创建索引时,您还可以进行相关设置:

创建索引而不设置任何内容的请求如下:

响应正文中的“acknowledged”表示已经在Elasticsearch集群中成功创建了索引,“shards_acknowledged”表示在请求超时之前已经准备好了索引片段的所有副本片段。当然,即使“acknowledged”和“shards_acknowledged”都为假,也只能说明在超时前索引没有完成,后续的集群可能最终会成功创建索引。

用于创建索引的API还支持查询参数和请求体,其中的参数是可选的。

查询参数支持以下参数:

请求正文还支持三个参数:

下面的代码示例指定了查询参数和请求正文:

通过Get index API,可以查询一个或多个索引的相关信息。API格式如下:

目标可以是数据流、索引或别名。多个索引用逗号分隔。目标也支持模糊查询(*)。如果查询所有索引,可以使用*或_all。如果集群中开启了安全权限控制,则需要获得view_index_metadata的索引操作权限或者设法查询索引信息。下面是一个具体的查询案例:

Get index API支持带url的查询参数。这些参数是可选的,主要包括以下内容:

首先,我们需要明确的是,指标本身是不能修改的。当我们说修改索引时,我们实际上是指修改索引的别名、字段映射和设置。

首先解释一下别名的作用。Elasticsearch提供了别名的功能,一个别名可以添加多个索引,方便通过操作一个别名来实际操作多个具体的索引。比如每年建一个指数,包括四个指数:index-2019,index-2020,index-2021,index-2022 * *,这四个指数都是有联系的。

其实别名的修改就是从索引中删除别名,然后重新添加一个新的别名。这两个动作放在一起是为了保证它的原子性,保证别名在被删除的那一刻不会出现不指向任何索引的问题。

以下代码从索引my-index-000001解除绑定my-index,然后将其重新绑定到索引my-index-000002。

映射指定索引的数据结构和字段类型,修改索引的映射,并可以修改原始字段的名称和类型以及添加新字段。下面是添加一个新的关键字类型的电子邮件字段。

支持多个索引、数据流和别名,支持模糊搜索,使用*或_all指定所有数据流和别名。

以下是修改设置的情况。设置索引有两个主切片和两个副本。

删除索引将删除其相应文档、片段和簇的元数据信息。指数的操作是高风险操作,需要谨慎。如果集群开启安全权限控制,需要获得delete_index的索引操作权限或者设法删除索引。

您不能删除数据流的写索引。若要删除当前的写索引,必须翻转数据流并创建新的写索引。

删除索引的API如下:

是一个必需的参数,用于指定索引名称。多个索引可以用逗号分隔,不支持别名,默认情况下不支持模糊匹配。如果真的需要模糊匹配,就需要设置集群参数action。destructive _ requires _ name为false。删除索引API类似于获取索引API,也支持URL查询参数。这些参数包括allow _ no _ indicators、expand_wildcards、ignore_unavailable、master_timeout和timeout,这些参数的含义相似,在此不再赘述。以下是删除索引的案例代码:

默认情况下,一旦创建了索引,它将处于打开状态。但是,在某些情况下,可能需要关闭索引,例如,一些旧的和不必要的索引仍然占用一定的空间,集群仍然需要一些维护费用。关闭索引将阻塞对此索引的所有读/写操作,关闭的索引不需要维护索引或搜索文档的内部数据结构,从而减少集群上的开销。

特别注意:关闭索引会消耗大量的磁盘空间,也是生产中需要特别注意的操作。可以通过集群设置API将cluster . indexes . close . enable设置为false来禁用索引的关闭,默认值为true。

当索引打开或关闭时,主节点负责重新启动片段,这些片段将经历恢复过程。索引打开或关闭后,会自动复制碎片数据,保证有足够的重复碎片,保证高可用性。

默认情况下,仅支持与全名匹配的特定索引,但是如果参数action。destructive _ requirements _ name设置为false,可以使用*或_all来引用所有索引,但这种情况下,一旦某个索引匹配失败,就会报错,不建议打开。

Open API用于重新打开关闭的索引。如果目标是数据流,那么对应于该数据流的所有索引都将被打开。

默认情况下,仅支持与全名匹配的特定索引,但是如果参数action。destructive _ requirements _ name设置为false,可以使用*或_all来引用所有索引,但是在这种情况下,一旦某个索引匹配失败,就会报错。

指数收缩和分裂是指收缩或分裂指数的主要部分的数量。首先,我们要明白为什么要收缩拆分指数。

在elasticsearch中,主节点管理碎片的工作量很大。减少整个集群中的碎片数量可以减少恢复时间、集群状态的大小和集群的维护消耗。很多情况下,一些冷索引运行一段时间后就没有数据可写了,合并一些小碎片可以降低集群的维护成本。

另一方面,如果在业务运营过程中发现,由于业务量大,预估不足,单个碎片过大,则需要拆分指标,扩大主碎片数量。

首先,指数收缩

Elasticsearch从5.0版本开始就提供了shrink API,用于减少一些小索引的索引碎片数量。实际上并没有操作源索引,而是创建了一个与源索引配置相同的新索引,只是减少了碎片的数量。索引碎片减少后,可以删除源索引。

为了能够通过收缩API进行切片和收缩,索引需要满足以下三个条件:

为了使碎片的分配更容易,可以先删除索引的复制碎片,在收缩操作完成后再重新添加复制碎片。

您可以使用以下代码删除所有副本切片,将所有主切片分配给同一节点,并将索引状态设置为只读:

重新分配源索引的片段可能需要一些时间。您可以使用_cat API来跟踪进度,或者使用集群健康API来等待通过wait _ for _ no _ relocation _ shards参数重新分配所有碎片。

以上步骤完成后,就可以进行收缩操作了。以下是_shrink API的格式:

在下面的例子中,索引my-index-000001被缩减为shrinked-my-index-000001。

特别注意:因为目标片段是在添加新文档时使用片段号的余数获得的,所以目标索引中请求的主片段数必须是源索引中主片段数的一个因子。例如,包含8个主切片的索引可以收缩到4、2或1个主切片,或者包含15个主切片的索引可以收缩到5、3或1个主切片。如果索引中的片数是质数,那么它只能减少为主片。

如果当前索引是数据流的写索引,则不允许收缩索引。您需要翻转数据流并创建新的写索引来收缩当前索引。

指标收缩的整个过程如下:

类似地,Elasticsearch还提供了一个Split API,用于将一个索引拆分成一个包含更多主切片的新索引。拆分API的格式如下:

要完成整个拆分操作,需要满足以下条件:

以下API请求可以使索引成为只读的:

如果当前索引是数据流的写索引,则不允许进行索引拆分。在拆分当前索引之前,需要翻转数据流并创建新的写索引。

以下是使用Split API进行索引拆分的请求案例,Split API支持设置和别名。

index.number_of_shards指定的主切片数必须是源切片数的倍数。

索引拆分可以拆分的碎片数量由参数index.number_of_routing_shards确定,路由碎片的数量指定哈希空间,哈希空间在内部用于以一致哈希的形式在碎片之间分发文档。例如,一个包含5个段且number_of_routing_shards设置为30(5 x 2 x 3)的索引可以拆分为2次或3次。换句话说,它可以分解如下:

5 10 30(依次拆分为2和3)

5 15 30(依次拆分为3和2)

5 30(分成6份)

Index.number_of_routing_shards是一个静态配置,可以在创建索引或在封闭索引上设置索引时指定。其默认值取决于原始索引中主切片的数量。默认情况下,允许通过2的倍数分割多达1024个切片。但是,必须考虑主切片的原始数量。例如,用5个切片创建的索引可以分为10、20、40、80、160、320或最多640个切片。

如果源索引只有一个主切片,则可以将其拆分成任意数量的主切片。

2.2、指标拆分的工作流程

2.3.为什么Elasticsearch不支持增量重分割?

大多数键值存储支持随着数据的增长自动扩展自动碎片。为什么Elasticsearch不支持?

最经典的方案是添加一个片段,然后将新数据存储在这个新添加的片段中。但是这种方案可能会造成Elasticsearch的索引瓶颈,整体结构会变得更加复杂,因为Elasticsearch需要定位文档属于哪个片段,这意味着需要使用不同的哈希方案来重新平衡现有的数据。

在键值存储系统中解决这个问题的方法通常是使用一致的散列。当片数从N增加到N+1时,一致哈希只需要重新分配1/N的键,比如redis集群的解是lace。

但Elasticsearch片段的底层其实是Lucene索引,从Lucene索引中删除一小部分数据通常比key-value存储系统的开销要大得多。因此,Elasticsearch选择在索引级别拆分文件,并使用硬链接高效地复制文件,以避免在索引之间移动文档。

对于在不修改或删除的情况下追加数据的场景,您可以通过创建一个新索引并将新数据推送到该索引中,并添加一个别名来读取旧索引和新索引,从而获得更大的灵活性。假设旧索引和新索引分别有M个和N个片段,这与搜索一个有M+N个片段的索引相比没有开销。

2.4.如何监控拆分的进度?

使用Split API拆分索引,API的正常返回并不意味着拆分的过程已经完成,只意味着创建目标索引的请求已经完成,集群状态已经添加。此时,主碎片可能没有被分配,并且副本碎片可能没有被成功创建。

一旦分配了主片,状态将是正在初始化,分割过程将开始。在拆分过程完成之前,该切片的状态将变为活动。

您可以使用_cat recovery API来监控分割过程,或者通过将wait_for_status参数设置为黄色,使用集群健康API来等待分配所有主片。

Elasticsearch克隆API可用于复制和备份弹性搜索索引数据。

第二,索引克隆API

索引克隆不会克隆源索引的元数据,包括别名、ILM阶段定义和CCR follower相关信息。克隆API将复制除index.number_of_replicas和index.auto_expand_replicas之外的所有配置。这两种特殊配置可以在克隆API的请求中明确指定。克隆API的格式如下:

索引满足可以克隆的条件:

参考我之前说的,通过将index.blocks.write设置为true,仍然可以确保索引可读。下面是一个克隆API的案例:

注意:index.number_of_shards的值必须与源索引的主切片数一致。

第三,索引克隆的过程

第四,监控克隆的进展

当使用克隆API克隆索引时,API的正常返回并不意味着克隆的过程已经完成,只意味着创建目标索引的请求已经完成,集群状态已经加入。此时,主片段可能没有被分配,并且副本片段可能没有被成功创建。

一旦分配了主分区,状态将是initializing,克隆过程将开始。在克隆过程完成之前,分区的状态将变为活动。

您可以使用_cat recovery API来监视克隆过程,也可以通过将wait_for_status参数设置为黄色,使用集群健康API来等待分配所有主片。

Rollover API是Elasticsearch提供的一个非常有用的功能。我们都知道在MySQL中,一旦数据量比较大,可能会出现分数据库、分表的情况,比如按照时间每个月一个表。翻转功能与这种情况类似。它的原理是先创建一个带别名的索引,然后设置一定的规则(比如满足一定时间范围的条件)。当满足设定的规则时,Elasticsearch会自动创建新的索引,别名会自动切换指向新的索引,相当于在物理层面自动建立索引分区功能。当查询数据落在一定时间内时,会在一个比较小的索引中进行查询,这个索引比较小。

翻转API将为数据流或索引别名创建新的索引。(在Elasticsearch 7.9之前,时间序列数据一般采用索引别名管理。Elasticsearch之后,数据流取代了这个功能,需要的维护更少,自动与数据层集成)。

滚动API的效果因要滚动的索引的别名而异:

使用翻转API时,如果指定新索引的名称,而原始索引以“-”和数字结尾,则新索引将保留名称并增加数字。例如,如果原始索引是my-index-000001,则新索引将是my-index-000002。

如果对时间序列数据使用索引别名,可以在索引名称中使用日期来跟踪滚动日期。例如,您可以创建一个别名来指向名为。如果索引创建于1999年5月6日,则索引的名称为My-Index-May 6,2099-000001。如果在1999年5月7日滚动别名,则新索引的名称为my-index-2099.05.07-000002。

翻转API的格式如下:

Rollover API还支持查询参数和请求体,其中查询参数支持wait_for_active_shards、master_timeout、timeout和dry_run,尤其是dry_run。如果将dry_run设置为true,那么这个请求将不会被实际执行,但是它会检查当前索引是否满足指定的条件,这对于预先测试非常有用。

请求体支持别名、映射和设置(这三个参数只支持索引,不支持数据流)和条件。

尤其是谈条件。这是一个可选参数。如果指定了条件,则仅当满足由条件指定的一个或多个条件时,才执行滚动。如果没有指定条件,滚动将是无条件的。如果需要自动滚动,可以使用ILM翻转。

条件支持以下属性:

下面是翻转中数据流的一个例子:

响应信息如下:

下面是翻转的索引别名的一个例子:

2.请求滚动API

如果别名的索引名称使用日期数学表达式,并且索引以固定间隔滚动,则可以使用日期数学表达式来缩小搜索范围。例如,下面的搜索目标是最近三天创建的索引。

索引冻结是Elasticsearch提供的一种减少内存开销的操作。在7.14版中,此函数被标记为不推荐使用。8版本以后,堆内存的使用得到了改进,冻结和解冻的功能不再适用。

下面是一个简单的操作演示。如果是7.x版本,还是可以作为参考的。

一.指数冻结

索引冻结后,除了在内存中维护元数据之外,集群上几乎没有任何开销。冻结后,索引是只读的,所有写操作都将被阻止,如文档写和合并。

API格式如下:

下面是一个索引冻结操作的代码案例:

请注意,冻结索引将关闭它,并在同一个API调用中重新打开它,这将导致主分配在短时间内没有被分配,并且集群变为红色,直到分配再次完成。

第二,指数解冻

冻结和解冻相应索引的API格式如下:

下面是一个索引解冻操作的代码案例:

Elasticsearch提供Resolve index API来辅助索引解析。根据提供的索引/别名/数据流的名称或模式匹配,可以找出当前簇中匹配索引的信息。以下是API的格式:

案例如下:

这个API的功能大多是辅助性的,实际中用的不多。详细参数请参考官方文档。

和我一起成为弹性专家吧。