添加 Elasticsearch v2 存储驱动

https://storyboard.openstack.org/#!/story/2006332

问题描述

目前只有一种 v2 存储驱动:InfluxDB。但是,对于 CloudKitty 的每个模块,应该始终有几个建议的选择。

以下优势使 Elasticsearch 成为一个极佳的候选者

  • 它是一种广泛使用的解决方案。 在大多数部署中,很可能已经有一个 Elasticsearch 集群可用(例如,用于日志集中)。

  • HA 和集群。 Elasticsearch 默认提供 HA 和集群功能,而 InfluxDB 的付费版本才提供这些功能。

  • 性能良好。 并且 Elasticsearch 允许管理员进行一些调整。

  • 数据可视化。 可以使用 Grafana 可视化 InfluxDB 存储驱动程序的数据,Elastic 堆栈提供 Kibana。

提议的变更

通过 cloudkitty.storage.v2.backends.elasticsearch 入口点可用的 Elasticsearch v2 存储驱动程序。

以下是针对 v2 存储驱动程序接口的每个方法的路由和聚合方法摘要

  • init: PUT /<index> 请参阅“数据模型影响”了解映射详细信息。

  • push: POST /<index>/<mapping>/_bulk

  • retrieve: GET /<index>/_search 带有过滤器的标准搜索查询。

  • total: GET /<index>/_search 将使用 composite 聚合:几个 terms 聚合在 bool 查询的 must 子句中将允许按特定属性对数据进行分组。然后将应用 sum 聚合到桶中,以获得每个桶的数量和价格。

  • delete: POST /<index>/_delete_by_queryretrieve 方法相同原理,但用于删除。

警告

“composite”查询自 Elasticsearch 6.5 版本以来一直稳定。为了与 6.x 和 7.x 兼容,cloudkitty 将使用 include_type_name 参数进行映射创建。该参数是在 Elasticsearch 6.8 中添加的。该参数将在 Elasticsearch 8 中删除。因此,CloudKitty 需要 Elasticsearch >= 6.5 且 < 8。

注意

关于分页: 鉴于 offset + sizesearch API 中不能超过 15000,retrieve 函数将使用滚动。将不会使用 search_after 功能,因为它是一种无状态功能,这意味着连续的请求可能会根据同时发生索引更新而返回意外的结果。应通过配置文件中的标记为 高级 的选项来配置应保持滚动上下文打开的持续时间。

total 函数将使用 composite 聚合的 after 参数

注意

CloudKitty 存储驱动程序只需要 Elasticsearch 的 OSS 版本即可工作。但是,Basic 版本的某些 X-Pack 功能(例如身份验证)将在未来支持(但不强制)。

备选方案

无。

数据模型影响

在 Elasticsearch 中使用的数据模型如下

每个 DataPoint 将是一个单独的文档。需要一个现有的空索引(这将允许管理员进行调整)。为了提高整体性能,将创建一个具有以下属性的映射。

  • start: (date) 数据点适用的时间段的开始时间。

  • end: (date) 数据点适用的时间段的结束时间。

  • type: (keyword) 数据点的类型。

  • unit: (keyword) 数据点的单位。

  • qty: (double) 数据点的数量。

  • price: (double) 数据点的价格。

  • groupby: (object) 数据点的 groupby 属性的字典。

  • metadata: (object) 数据点的 metadata 属性的字典。

注意

为了允许灵活的 groupby/metadata,相关的对象将是灵活的。

注意

鉴于我们将只进行精确值搜索,每个 string 属性都将被转换为 keyword。这将使用动态模板来实现。

警告

默认情况下,将启用 _source 字段。可以添加一个选项来禁用它以提高存储大小,但应该谨慎操作。有关详细信息,请参阅参考资料中的 Elasticsearch 文档链接。

最终,映射将定义如下

{
  "mappings": {
    "_doc": {
      // cast all strings to keywords
      "dynamic_templates": [
        {
          "strings_as_keywords": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ],
      // we won't add any attribute to the base object, so dynamic must be false
      "dynamic": false,
      "properties": {
        "start": {"type": "date"},
        "end": {"type": "date"},
        "type": {"type": "keyword"},
        "unit": {"type": "keyword"},
        "qty": {"type": "double"},
        "price": {"type": "double"},
        // groupby and metadata will accept new attributes
        "groupby": {"dynamic": true, "type": "object"},
        // even though metadata should not be indexed, disabling it can't be
        // undone, and disabled objects are only available through the "_source"
        // field, which may also be disabled
        "metadata": {"dynamic": true, "type": "object"}
      }
    }
  }
}

注意

鉴于用于过滤的术语可能是 groupbymetadata 的一部分,每个过滤器将向 bool 查询的 should 部分添加两个 term 查询(一个用于 groupby 部分,一个用于 metadata 部分)。因此,bool 查询的 minimum_should_match 参数将设置为 should 查询中术语数量的一半。

REST API 影响

无。

安全影响

在第一轮迭代中,将不支持 x-pack 身份验证。管理员将负责保护 Elasticsearch 集群与 CloudKitty 之间的连接。身份验证将在未来的版本中引入。

通知影响

无。

其他最终用户影响

无。

性能影响

在大多数基准测试(以及从 POC 中可以确定的结果)中,将数据插入到 Elasticsearch 比插入到 InfluxDB 慢。但是,Elasticsearch 在聚合方面更快。但是,一旦 CloudKitty 赶上了当前时间戳,就不需要太多的插入了。此外,Elasticsearch 对集群和调整的支持应该最终能够提供更好的整体性能。

其他部署者影响

新的后端将需要管理员进行更多的配置

  • 索引别名和生命周期

  • 分片和副本

开发人员影响

实现

负责人

主要负责人

peschk_l

工作项

  • 实现 Elasticsearch 存储驱动程序

  • 将对驱动程序的支持添加到 Devstack 插件。

  • 添加一个 Tempest 作业,其中使用 Elasticsearch 存储驱动程序。

依赖项

Elasticsearch >= 6.5。

测试

除了单元测试之外,还将使用 Tempest 进行测试。

文档影响

将详细说明此驱动程序提供的配置选项,文档中还将有一个专门用于配置 Elasticsearch 索引的部分。

参考资料