亚马逊AWS官方博客

使用 Elasticsearch 的 _rollover API 以提高存储分配的效率

许多 Open Distro for Elasticsearch 用户通过创建基于标准时间段的索引来管理其集群的数据生命周期,通常每天一个索引。这种模式有许多优势:Logstash 等提取工具支持索引的直接滚动;保留期限的定义十分简单直接;旧数据的删除也简单至将索引丢弃即可。

如果您的工作负载有多个数据流,并且每个流有不同的数据大小,那么您可能会遇到问题:您的资源使用量(尤其是每个节点的存储使用量)可能会变得失衡,或者说发生“偏斜”。 发生这种情况时,一些节点将会过载或比其他节点更早耗尽存储,并且您的集群可能会停止运行。

您可以使用 _rollover API 来管理索引的大小。您可以使用一个定义了 Elasticsearch 何时应创建新索引并开始写入的阈值,按照固定的周期调用 _rollover。这样,每个索引会尽可能保持相同的大小。在 Elasticsearch 将索引所用的分区分配给集群中的节点时,您会尽可能均匀地使用各个节点的存储。

什么是偏斜?

Elasticsearch 主要根据各个节点的分区数量来向节点分配分区(实际当然更为复杂,但这是一个很好的类比)。如果您只有一个索引,由于分区大小基本相同,您可以通过让分区数量可被节点数量整除的方式来确保数据的均匀分布。例如,如果您有五个主分区和一个副本,或者总计有十个分区,并且您部署了两个节点,则每个节点上将有五个分区(Elasticsearch 始终会将主分区及其第一个副本放在不同的节点中)。

 

两个分区使用量均衡的 Open Distro for Elasticsearch 节点

 

如果您有多个索引,则每个节点的存储将会不均匀。例如,假设您的应用程序每天生成 1GB 的日志数据,而您的 VPC 流日志每天生成 10GB 的日志数据。对于这两个数据流,您按照每个分区不超过 50GB 的最佳实践,使用一个主分区和一个副本。再假设您的集群中有六个节点。在七天后,每个索引总计将有 14 个分区(每天一个主分区和一个副本)。您的集群可能会看起来与以下类似 — 在最佳情景中,您的数据分布是均匀的:

 

资源使用量均衡的 Open Distro for Elasticsearch 集群

在最差的情景中,假设您有五个节点,并且您的分区数量不能用节点数整除,因此较大的分区可能占据一个节点,如下图所示。含有较大分区的节点使用的存储量是含有较小分区的节点的十倍。

资源使用量不均衡的 Open Distro for Elasticsearch 集群

尽管此例有些虚构的成分,但也说明了 Elasticsearch 用户必须解决的真实问题。

改用滚动!

_rollover API 会在您触及您在调用中定义的阈值时创建新的索引。您首先会创建一个 _alias 用于读取和写入当前索引。然后您使用 cron 或其他调度计划工具来定期调用 _rollover API,例如每分钟一次。当您的索引超过阈值时,Elasticsearch 会在别名后创建新的索引,并且您继续向该别名写入。

要为您的索引创建别名,您需要调用 _aliases API:

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "weblogs-000001",
        "alias": "weblogs",
        "is_write_index": true
      }
    }
  ]
}

您必须将 is_write_index 设置为 true 以告诉 _rollover 它需要更新哪个索引。

当您调用 _rollover API 时:

POST /weblogs/_rollover 
{
  "conditions": {
    "max_size":  "10gb"
  }
}

您将收到一条应答,详细说明哪个条件(如有)为真,以及 Elasticsearch 是否因为该调用而创建了新的索引。如果您通过添加结尾编号的方式为索引命名(例如 -000001),Elasticsearch 会在创建下一个索引时递增该编号。如果为哪种情况,您都可以继续不间断地向别名写入。

Elasticsearch 7.x 接受三种条件:max_age、max_docs 和 max_size。如果您使用同样的 max_size 对您的所有索引调用 _rollover,则它们将全部以基本相同的大小滚动。[注意:在分布式系统中,大小难以锁定。不要期望大小会完全相同。有差异是正常的。实际上,早期版本的 Elasticsearch 不接受将 max_size 作为条件。对于这些版本,您可以使用 max_docs,从而确保文档大小的标准化。]

一个重要的权衡之处是生命周期管理。回到我们之前的示例,假设您滚动一个 10GB 的索引。每天 10GB 的数据流将每天滚动。每天 1GB 索引的数据流将每 10 天滚动一次。您需要根据索引的大小在不同的时间管理这些索引。较低容量索引中的数据保持的时间要长于较高容量索引中的数据。

小结

运行含有多个不同大小数据流的 Elasticsearch 集群(通常是出于分析目的)时,您可以使用 _rollover API 来保持集群节点中的数据更加接近均匀分布。这可以防止存储使用量的偏斜,提高集群的稳定性。

有问题或疑问? 希望参与讨论? 您可以在我们的论坛上获得帮助并讨论 Open Distro for Elasticsearch。您可以在这里提出问题