Elasticsearch 中的索引模板:如何使用可组合模板
作者:来自 Elastic Kofi Bartlett
探索可组合模板以及如何创建它们。
更多阅读: Elasticsearch:可组合的 Index templates - 7.8 版本之后
想获得 Elastic 认证吗?查看下一期 Elasticsearch Engineer 培训的时间!
Elasticsearch 拥有大量新功能,帮助你为你的使用场景构建最佳搜索方案。深入学习我们的示例 notebook,了解更多信息,开始免费的 cloud 试用,或者现在就在你的本地机器上尝试 Elastic 吧。
Elasticsearch 索引可以通过 mapping、settings 和 aliases 进行配置:
-
Mapping 定义指定数据的 schema。
-
Settings 设置分片大小和刷新频率。
-
Aliases 用于为索引设置别名。
当我们第一次索引文档或使用 Create Index API 创建空索引时,该索引会使用默认设置创建,不包含数据 schema,也没有别名。这些默认设置在开发和测试环境中通常能正常工作,但在生产环境中我们可能需要对索引进行自定义。
在生产环境中使用默认的 mapping 和 settings 可能会导致索引和搜索性能不佳。手动创建索引既繁琐又耗时,尤其当我们有复杂的 mapping schema、自定义 settings 和 aliases 时,在每个环境中都重新创建这些索引非常不现实。
幸运的是,Elasticsearch 提供了一种工具,可以在创建索引时自动应用预定义的配置,这就是索引模板(index templates)。
索引模板
索引模板允许我们使用自定义配置来创建索引。索引在创建时可以从这些模板中获取配置,例如设置分片数量、副本数或字段 mapping。如果索引的名称与模板的命名模式匹配,Elasticsearch 就会使用模板中定义的配置来创建新索引。
Elasticsearch 在 7.8 版本中升级了模板功能,引入了 可组合模板(composable templates)。这一新版本提供了更高的模板重用性,本文就展示了这一点。
模板类型
索引模板可以分为两类:
-
索引模板(或可组合索引模板):可组合索引模板可以独立存在,也可以由一个或多个组件模板(见下)组合而成。
-
组件模板(component templates):组件模板是可复用的模板,定义了所需的配置。通常组件模板需要与索引模板关联使用。每个组件模板可以被一个或多个索引模板引用。
如下面的图片所示,索引模板 A 和 B 共享组件模板(此例中是 Template 3)。一个索引模板可以包含零个或多个组件模板,而每个组件模板也可以关联零个或多个索引模板。虽然这两种模板都可以独立存在,但组件模板如果没有附加到索引模板上,就没有实际用途。
总体思路是为组织开发一套组件模板目录,以满足各种需求(例如为不同环境指定不同的组件模板),并通过可组合索引模板将它们附加到各个索引上。
如何创建可组合(索引)模板
Elasticsearch 提供了一个 _index_template
端点,用于管理索引模板。用户在该模板中提供所有需要的 mappings、settings 和 aliases,以及一个索引名称模式。我们来看一个为微服务应用 customer-order-service
创建模板的例子,该服务负责订单生成逻辑。
假设我们的需求是为客户订单创建一个模板,名称模式使用通配符:*orders
。此模板应包含某些 mappings 和 settings,例如 order_date
字段,以及分片数和副本数。
任何在创建过程中与该模板匹配的索引都会继承模板中定义的配置。例如,black_friday_orders
索引将包含 order_date
字段,分片数将设置为 5,副本数设置为 2。除此之外,所有从该模板创建的索引还会继承一个统一的别名。我们将创建一个名为 orders_template
的模板,索引模式为 *orders
,其 mapping schema 包含一个 order_date
字段,使用预定义的日期格式 dd-MM-yyyy
。以下是创建该索引模板的代码:
PUT _index_template/orders_template
{"index_patterns": ["*orders"],"priority": 300,"template": {"mappings": {"properties": {"order_date": {"type": "date","format":"dd-MM-yyyy"}}},"settings":{"number_of_shards":5,"number_of_replicas":2},"aliases":{"all_orders":{}}}
}
当你在 Kibana 的 DevTools 中执行这个查询时,模板会使用索引模式 *orders
被创建,并包含预定义的 mapping、settings 和一个 alias。index_patterns
是一个匹配模式数组;任何匹配该模式的索引都会继承模板配置。你可以执行以下命令来获取已保存的模板,以验证我们刚才所做的操作:
GET _index_template/orders_template
创建模板时还定义了一个优先级属性,这是一个正整数:每个模板都有一个优先级,以便在多个模板之间存在冲突时,通过该值来决定使用哪个模板,优先级越高越优先。我们将在下面更深入地探讨模板优先级。
使用模板创建索引
现在我们已经有了一个模板——用于创建索引的蓝图——下一步是创建一个索引。当索引名称与给定模式匹配时,模板中的配置会被自动应用。为了验证这一点,如下所示的代码创建了一个全新的索引,名为:blackfriday_orders
:
PUT blackfriday_orders
由于索引名称(blackfriday_orders
)与模板中定义的命名模式(即 *orders
)匹配,该索引应继承模板中的所有配置。我们可以通过执行以下代码来获取这个新创建的索引,并检查是否确实如此:
GET blackfriday_orders
这应该返回:
{"blackfriday_orders" : {"aliases" : {"all_orders" : { }},"mappings" : {"properties" : {"order_date" : {"type" : "date","format" : "dd-MM-yyyy"}}},"settings" : {"index" : {..."number_of_shards" : "5","number_of_replicas" : "2"}}}
}
正如响应所示,blackfriday_orders
的配置已经从模板中继承。我们可以尝试不同的索引组合,这些组合将成功继承模板配置:
PUT blackfriday_orders
PUT americaorders
PUT cancelled--orders
PUT undefined101orders
然而,以下索引将不会继承配置,因为它们的名称与模式不匹配:
PUT blackfriday_orders2
PUT open_orders_
PUT allorders_total
需要记住的一件重要事情是,所有从模板派生的索引都拥有相同的别名 —— 在此情况下为 all_orders
。拥有这样的别名是有优势的 —— 我们可以简单地查询这个单一的别名,而不是查询多个索引。
GET blackfriday_orders,americaorders,undefined101orders/_search
GET all_orders/_search
{"query": {"range": {"order_date": {"gte": "01-12-2021","lte": "31-12-2021"}}}
}
在为 *orders
创建模板时,任何匹配的索引都应该采用该模板配置。通常,无论是有意还是无意,团队可能会根据各种原因创建更多模板。这意味着有时索引名称可能会匹配两个不同的模板模式!Elasticsearch 必须决定应用这两个模板中的哪一个配置。幸运的是,这个难题可以通过使用模板优先级来解决。
创建组件模板
我们在文章的前面部分了解了索引模板。直接在模板中内置配置有几个缺点 —— 其中一个缺点是配置不能导出供其他模板使用。如果我们希望有类似的配置,比如用于客户相关模板(*customers
),可能需要重新创建整个模板。这意味着,在一个典型的组织中,我们可能需要创建数十个这样的模板(再加上根据环境可能需要更多模板)。
由于我们总是追求可重用性,Elasticsearch 重新设计了模板,考虑到了可重用性。组件模板正好满足了这一需求。如果你来自 DevOps 背景,很可能你需要为每个环境创建带有预设配置的索引。与其费力地手动应用这些配置,不如为每个环境创建一个组件模板。
组件模板不过是一个可重用的配置块,我们可以用它来构建更多的索引模板。请注意,组件模板只有与索引模板配合使用时才有意义。它们通过 _component_template
端点暴露出来。让我们看看这些是如何组合在一起的。
设置模板
让我们从之前在索引模板中定义的设置中提取,并创建一个组件模板。settings_component_template
预计将具有五个主分片,每个主分片有两个副本。第一步,如下面的代码所示,是声明并执行一个具有此配置的组件模板。
PUT _component_template/settings_component_template
{"template":{"settings":{"number_of_shards":5,"number_of_replicas":2}}
}
如上面的代码所示,我们使用 _component_template
端点来创建一个组件模板。请求的主体包含一个模板对象,其中包含模板信息。settings_component_template
现在可以在其他索引模板中使用。一个显著的区别是,这个模板没有定义任何索引模式;它只是一个配置我们一些属性的代码块。
映射模板
以相同的方式,让我们创建另一个模板。这次,我们将提取之前在独立索引模板中定义的映射 schema。下面的代码展示了脚本:
PUT _component_template/mappings_component_template
{"template": {"mappings": {"properties": {"order_date": {"type": "date","format":"dd-MM-yyyy"}}}}
}
别名模板
按照相同的流程,我们也可以创建一个包含别名的组件模板——两个别名(all_orders
和 sales_orders
):
PUT _component_template/aliases_component_template
{"template": {"aliases": {"all_orders": {},"sales_orders":{}}}
}
可组合索引模板
现在我们有了这三个组件模板,下一步是将它们投入使用。我们可以通过让一个索引模板(比如 christmas_orders
)使用它们来实现:
PUT _index_template/composed_orders_template
{"index_patterns": ["*orders"],"priority": 500,"composed_of": ["settings_component_template","mappings_component_template","aliases_component_template"]
}
composed_of
标签是由所有构成该模板的组件模板组成的集合。在这个例子中,我们选择了 settings
、mappings
和 aliases
组件模板。我们还提高了优先级,使得这个模板的优先级高于其他模板。一旦模板准备好,任何匹配 *orders
模式的索引将从这三个组件模板继承配置。
话虽如此,如果我们希望创建一个新的模板,比如 customers
,只使用现有的一个模板(settings_component_template
)和一个新创建的别名模板(aliases_component_template
,见下文),我们可以通过以下方式实现:
PUT _component_template/aliases_component_template2
{"template": {"aliases": {"all_customers": {}}}
}
索引模板如下所示:
PUT _index_template/composed_customers_template
{"index_patterns": ["*customers*"],"priority": 200,"composed_of": ["settings_component_template","aliases_component_template2"]
}
你看到 settings_component_template
已经在两个不同的模板中被(重新)使用了吗?这就是组件模板的优势。
模板优先级
开发人员有可能创建多个索引模板,而没有查看现有的模板库。因此,为每个模板设置优先级很重要,这样具有更高优先级的模板将被使用。例如,my_orders_template_1
会覆盖 my_orders_template_2
,如下代码片段所示:
PUT _index_template/my_orders_template_1
{"index_patterns": ["*orders"],"priority": 1000,"template": { ... }
}PUT _index_template/my_orders_template2
{"index_patterns": ["*orders"],"priority": 300,"template": { ... }
}
当你有多个模板匹配正在创建的索引时,Elasticsearch 会应用所有匹配模板的配置,但会覆盖具有更高优先级的配置。
模板的优先级
最后,你可能会想知道模板的优先级问题 —— 组件模板中定义的配置是否会覆盖主索引模板中定义的配置?还是反过来?实际上,有一些规则:
-
使用显式配置创建的索引会优先于所有其他配置 —— 这意味着,如果你使用显式配置创建索引,不要期望这些配置会被模板覆盖。
-
旧版本的模板(在 7.8 版本之前创建的模板)的优先级低于可组合模板。
总结
- 一个索引包含映射、设置和别名:映射定义字段的架构,设置设置索引参数,如分片数和副本数,别名为索引提供备用名称。
- 模板允许我们创建具有预定义配置的索引。将索引命名为与特定模板中定义的索引模式匹配的名称时,该索引会根据模板自动配置。
- Elasticsearch 在 7.8 版本中引入了可组合索引模板。可组合索引模板允许模板的模块化和版本管理。
- 可组合模板由一个或多个组件模板组成。
- 索引模板也可以定义自己的配置。
- 组件模板是一个具有预定义配置的可重用模板,就像一个可组合索引模板。
- 然而,组件模板预计会成为索引模板的一部分;如果没有被“组合”到索引模板中,它们是无效的。
- 组件模板中没有定义索引模式 —— 这也是它们 “预计” 成为索引模板一部分的原因。
- 每个模板都有一个优先级 —— 一个正数。数字越大,应用该模板的优先级越高。
原文:Index templating in Elasticsearch: How to use composable templates - Elasticsearch Labs